2009-05-13 5 views
16

Ich habe gelegentlich Klassen mit privaten statischen Datenelementen. Ich diskutiere gerade, ob ich diese durch statische Variablen in einem unbenannten Namespace in der Implementierungsdatei ersetzen sollte. Andere, die diese Variablen nicht in Inline-Methoden verwenden können, gibt es noch andere Nachteile? Der Vorteil, den ich sehe, ist, dass sie vollständig vor den Benutzern der Klasse verborgen sind.statische Klassendaten vs anonyme Namespaces in C++

Antwort

4

Ich bin nicht davon überzeugt, dass der Vorteil die Lesbarkeit Auswirkungen wert ist. Generell halte ich etwas Privates für "versteckt genug".

1

Es verbirgt sie nicht nur vor Benutzern der Klasse, es verbirgt sie vor Ihnen! Wenn diese Variablen Teil der Klasse sind, sollten sie in irgendeiner Weise der Klasse zugeordnet werden.

Je nachdem, was Sie vorhaben, mit ihnen zu tun, könnten Sie betrachten sie als statische Variablen in statischen Member-Funktionen machen:

// header file 
class A { 
    public: 
    static void func(); 
}; 


// cpp file 
void A :: func() { 
    static int avar = 0; 
    // do something with avar 
} 
4

1) Es ist ein Nachteil in Form einer zusätzlichen Beschränkung binären Organisation . In einer Präsentation auf einer C++ - Konferenz in den 1990er Jahren berichtete Walter Bright, dass er durch die Organisation seines Codes signifikante Leistungssteigerungen erzielen konnte, so dass Funktionen, die sich gegenseitig ansprachen, in der gleichen Kompilierungseinheit waren. Wenn beispielsweise während der Ausführung von Class1 :: method1 weit mehr Aufrufe an Class2-Methoden als an anderen Class1 :: -Methoden vorgenommen wurden, bedeutete die Definition von Class1 :: method1 in class2.cpp, dass sich Class1 :: method1 auf derselben Codepage wie die Methoden befand es rief an und würde daher weniger wahrscheinlich durch einen Seitenfehler verzögert werden. Diese Art des Refactorings ist mit der Klassenstatik einfacher durchzuführen als mit der Dateistatik.

2) Eines der Argumente gegen Einführung des Namespace Schlüsselwort war „Sie können mit einer Klasse das gleiche tun,“ und Sie werden Klasse und Struktur zu sehen ist, als ein Arme-Leute-Namensraum in Quellen aus dem Pre verwendet -namespace Ära. Das überzeu- gende Gegenargument war, dass Namespaces wieder geöffnet werden können und jede Funktion überall sich zu einem Namespace oder einem fremden Namespace machen kann. Dann gibt es Dinge, die man mit einem Namespace machen könnte, den man mit einer Klasse machen kann . Dies wirkt sich auf Ihre Frage aus, da es darauf hindeutet, dass das Sprachkomitee den Namensraumbereich für sehr ähnlich hält wie den Klassenumfang; Dadurch wird die Wahrscheinlichkeit verringert, dass bei der Verwendung eines anonymen Namespace anstelle einer Klassenstatik eine geringfügige linguistische Falle auftritt.

+5

Denken Sie daran, dass das in den 90er Jahren war und dass Compiler bis zu dem Punkt fortgeschritten sind, wo Dinge wie VC++ 's ganze Programmoptimierung gut genug funktionieren, dass diese Art von Refactoring eine Verschwendung von Programmierzeit ist. –

+1

Hat Walter Bright gesagt, dass diese Art von Refactoring jetzt eine Verschwendung von Zeit ist? Eine der Fragen auf dieser Sitzung, die sich mit Fragen der Wartbarkeit befasste, lautete: "Wer, aber Sie werden in der Lage sein, solche Dinge zu tun, wenn Sie in Rente gehen?" zu denen Walter Worte mit der Bedeutung "Wenn ich in Rente gehe, Compiler werden langsamer" antworten. –

1

Ich denke, es läuft darauf hinaus, ob diese Variablen eine tatsächliche Bedeutung im Kontext der Klasse haben (zB Zeiger auf einen gemeinsamen Speicher, der von allen Objekten benutzt wird) oder nur einige temporäre Daten, die man zwischen Methoden passieren muss und würde Zerstreuen Sie die Klasse lieber nicht mit. Im letzteren Fall würde ich definitiv mit dem unbenannten Namensraum gehen. In ersterem würde ich sagen, es ist eine Frage des persönlichen Geschmacks.

2

Ich stimme nicht mit den anderen Antworten. Halten Sie so viel wie möglich von der Klasse Definition.

In Scott Meyers' Effective C++ 3rd edition empfiehlt er nicht-Freund Funktionen zu Klassenmethoden zu bevorzugen. Auf diese Weise ist die Klassendefinition als klein wie möglich, auf die privaten Daten wird in so wenigen Stellen wie möglich zugegriffen möglich (gekapselt).

Nach diesem Prinzip führt weiter zum pimpl idiom. Jedoch wird Balance benötigt. Stellen Sie sicher, dass Ihr Code wartbar ist. Blindly, nach dieser Regel würde Sie dazu führen, dass alle Ihre privaten Methoden Datei lokal und nur die erforderlichen Mitglieder als Parameter übergeben.Diese würde verbessern Verkapselung, aber die Wartbarkeit zu zerstören.

Alles, was gesagt wird, Datei lokale Objekte sind sehr schwierig zu Unit-Test. Mit cleveren Hacking können Sie während der Tests auf private Mitglieder zugreifen. Zugriff auf lokale Dateiobjekte ist ein wenig mehr involved.

1

Ich stimme teilweise mit Greg überein, dass unbenannte Namespacemitglieder nicht mehr gekapselt sind als private Daten. Der Punkt der Kapselung besteht schließlich darin, Implementierungsdetails von anderen Modulen zu verbergen, nicht von anderen Programmierern. Trotzdem denke ich, dass es in einigen Fällen eine nützliche Technik gibt.

Betrachten wir eine Klasse wie folgt aus:

class Foo { 
public: 
    ... 
private: 
    static Bar helper; 
}; 

In diesem Fall kann jedes Modul, das Foo verwenden möchte wissen muss auch die Definition der Bar, obwohl diese Definition nicht von Bedeutung ist, was so überhaupt. Diese Art von Header-Abhängigkeiten führen zu häufigeren und längeren Umbauten. Das Verschieben der Definition von helper in einen unbenannten Namespace in Foo.cpp ist eine großartige Möglichkeit, diese Abhängigkeit zu umgehen.

Ich stimme auch stark mit der Vorstellung überein, dass unbenannte Namespaces irgendwie weniger lesbar oder weniger wartbar als statische Datenmitglieder sind. Durch das Entfernen irrelevanter Informationen aus Ihrer Kopfzeile wird es nur prägnanter.