2012-12-29 4 views
7

Wenn ich objektorientierten Code in C schreibe, stelle ich normalerweise die Strukturdefinition zusammen mit den öffentlichen Funktionen in eine Headerdatei und implementiere die öffentlichen Funktionen in einer separaten .c-Datei. Ich gebe das statische Schlüsselwort allen Funktionen, die für diese Klasse "privat" sind, und implementiere sie auch in der .c-Datei. Die öffentlichen Funktionen können dann die privaten Funktionen aufrufen, die zu derselben Klasse gehören. Die privaten Funktionen können dank des Schlüsselworts "static" nicht von außen aufgerufen werden, sodass GCC viele dieser Funktionen optimieren kann. Sie sind oft inline und die ursprüngliche Funktion wird vollständig aus der Ausgabeobjektdatei gelöscht.Interne Verknüpfung für private C++ - Funktionen?

Nun zu meiner Frage: Wie kann ich das gleiche mit C++ - Klassen tun?

Lassen Sie uns sagen, dass ich eine Header-Datei haben:

class A { 
    int private_field; 
    int private_function(); 
public: 
    int public_function(); 
}; 

Und meine CPP-Datei:

#include <iostream> 
#include "A.h" 

int A::private_function() { 
    std::cin >> private_field; 
    return private_field; 
} 

int A::public_function() { 
    return private_function() + 4; 
} 

In der resultierenden Objektdatei private_function wird als separates Symbol links und public_function ruft private_function (nicht inline). Ich würde private_function interne Verknüpfung geben, so dass der Compiler die gleichen Optimierungen wie wenn ich C verwenden kann. Ich habe versucht, mit anonymen Namespaces und statische, aber ich kann es nicht so funktionieren, wie ich möchte. Wie geht es richtig, ist es überhaupt möglich? Ich benutze GCC.

+1

„Ich habe mit anonymen Namespace versucht und statisch, aber ich kann es nicht, wie ich möchte an die Arbeit.“ was schief gelaufen ist? –

+0

Ich habe Ihre Frage beantwortet, aber der Compiler sollte in der Lage sein, die meisten Optimierungen durchzuführen, z. B. Inlining, ohne dass dazu interne Verknüpfungen benötigt werden. –

+0

Inline wird manchmal ausgeführt (für kleine Funktionen), aber die Originale bleiben immer übrig => größere Bibliotheksgröße. – Emil

Antwort

8

Klassenmitglieder haben niemals interne Verknüpfungen. Die Norm sagt (Abschnitt 9.3):

Mitglied Funktionen einer Klasse im Namensraum Umfang externe Bindung hat. Mitgliedsfunktionen einer lokalen Klasse haben keine Verknüpfung.

Wenn Sie also Hilfsfunktionen mit interner Verknüpfung erstellen möchten, müssen Sie ein Nichtmitglied verwenden.

static int private_function(A* pThis); 

class A 
{ 
    int private_field; 
    friend int private_function(A* pThis); 
public: 
    int public_function(); 
}; 

und dann

#include <iostream> 
#include "A.h" 

static int private_function(A* pThis) 
{ 
    std::cin >> pThis->private_field; 
    return private_field; 
} 

int A::public_function() { 
    return private_function(this) + 4; 
} 

Bitte beachten Sie diese Regel aus dem Standard (Abschnitt 11.3):

Eine Funktion zunächst in einem Freund Erklärung erklärt hat externe Bindung. Andernfalls behält die Funktion ihre vorherige Verknüpfung bei.

+2

Ich denke, der Standard ist seltsam. Warum möchtest du eine externe Verbindung zu privaten Funktionen haben, wenn es keine Freunde gibt? – Emil

+6

@Emil: Weil dadurch die öffentlichen Mitglieder in anderen Übersetzungseinheiten eingebunden werden können. Überlegen Sie, ob in der Klasse "A :: public_function" inline deklariert wurde. Es ist kurz, also würde der Compiler es an allen Aufrufstellen, in welcher Übersetzungseinheit sie auch erscheinen mögen, einbinden.Aber dann muss 'private_function' an all diesen Sites verlinkt werden können. –