2010-03-17 5 views
25

Ich muss einige konstante Zeichenfolgen definieren, die nur von einer Klasse verwendet werden. Es sieht so aus, als ob ich drei Optionen habe:Wo setze ich konstante Zeichenfolgen in C++: statische Klassenmitglieder oder anonyme Namespaces?

  1. Betten Sie die Strings direkt an Orten ein, an denen sie verwendet werden.

  2. sich als private static Konstante Mitglieder der Klasse definieren:

    //A.h 
    class A { 
    private: 
        static const std::string f1; 
        static const std::string f2; 
        static const std::string f3; 
    }; 
    
    //A.cpp 
    const std::string f1 = "filename1"; 
    const std::string f2 = "filename2"; 
    const std::string f3 = "filename3"; 
    
    //strings are used in this file 
    
  3. sie in einem anonymen Namespace in der CPP-Datei definieren:

    //A.cpp 
    namespace { 
        const std::string f1 = "filename1"; 
        const std::string f2 = "filename2"; 
        const std::string f3 = "filename3"; 
    } 
    
    //strings are used in this file 
    

diese Optionen gegeben, die man würdest du empfehlen und warum? Vielen Dank.

+0

Danke für die Formatierung. – stone

+6

Beachten Sie, dass dies gefährlich ist, wenn Sie die Funktion, die diese Zeichenfolgen aus anderen Übersetzungseinheiten verwendet, vor dem Start von main aufrufen: Die Funktion kann dann auf die Zeichenfolgenobjekte zugreifen, bevor sie erstellt wurden. Aus diesem Grund würde ich die const std :: string-Objekte loswerden und 'char const f1 [] =" filename ";' dafür verwenden. –

+0

@litb: Es scheint, dass Sie sagen, dass es sicherer ist, in diesem Fall primitive Typ Char als das String-Objekt zu verwenden? Darf ich den Grund dafür wissen? – jasonline

Antwort

21

Ich würde sie in anonyme Namespace in der CPP-Datei platzieren. Sie macht sie für die Implementierung privat und macht sie gleichzeitig für die Nichtmitgliedsfunktionen sichtbar, die Teil der Implementierung sind (wie operator<<).

+0

Danke für den Zuspruch. Ich bin auch zu dieser Option geneigt. Diese Saiten wären am liebsten konstant. Aber wenn ich mich später dazu entschloss, einen der Dateinamen zu ändern, kann ich das problemlos tun, ohne mich darum zu kümmern, alles neu zu kompilieren, was die Header-Datei enthielt. – stone

+0

Es ist erwähnenswert, dass der eigentliche Text immer noch in der Implementierungsdatei enthalten sein muss, auch wenn Sie sie innerhalb der Klasse als statische Konflikte definieren. Wenn Sie also die Dateinamen ändern, müssen Sie nur diese eine Datei neu kompilieren. –

+0

Sie haben Recht, Dennis. Es macht nur einen Unterschied in Bezug auf das Kompilieren, wenn diese Konstanten hinzugefügt/gelöscht werden. Änderungen sollten gleich sein. – stone

2

Wenn die Zeichenfolgen von den Benutzern der Klasse angezeigt werden sollen, fügen Sie sie in die Klasse ein. Andernfalls blenden Sie sie im unbenannten Namespace der Implementierungsdatei aus.

5

Wenn sie nur in einer einzigen Datei verwendet werden, müssen sie nicht der Außenwelt zugänglich gemacht werden, indem sie in die Header-Datei aufgenommen werden.

Wenn sie verwendet werden und immer nur an einem einzigen Ort verwendet werden, dann gibt es wirklich keinen Grund, sie nicht einfach als Literale zu schreiben, wo sie gebraucht werden.

Wenn sie an mehreren Stellen in der cpp verwendet werden, würde ich für den anonymen Namespace gehen.

Eine andere Option, die Sie nicht erwähnen, ist, sie als statische Variablen innerhalb der cpp zu definieren. Dies entspricht in etwa der anonymen Namespace-Option und ist C-ähnlicher als C++.

3

Statische Mitglieder der Klasse.

Wenn sie von der einen Klasse an mehreren Stellen verwendet werden, ist es normalerweise einfacher, die Dinge zu organisieren - und später zu finden, wo Sie alles definiert haben - wenn Sie sie in der Klasse definieren, die sie verwendet. Wenn sie direkt definiert werden, können sie nur schwer gefunden und später geändert werden. Und ich würde mich für eine bestimmte Klasse über den anonymen Namespace entscheiden, um die Definition und Verwendung der Klasse zu vereinfachen.

0

Von den drei Optionen, die einzige, die Sie wirklich vermeiden sollten, ist # 1. Verwenden Sie keine magischen Cookies in Ihrem Code. Indem Sie die Konstanten entweder in einen Namespace oder eine Klasse einfügen, erleichtern Sie es, Ihren Code in Zukunft zu erweitern und zu pflegen.

Wenn Ihre Konstanten global sind, dann spielt es zwischen 2 und 3 keine Rolle. Entscheidend ist, dass Sie sich für eins entscheiden und dabei bleiben. Wenn Sie jedoch Konstanten haben, die für eine bestimmte Klasse gelten, sollten sie Teil dieser Klasse sein.

Persönlich würde ich einen Namensraum für die meisten Dinge verwenden.

0

Ich denke, das eigentliche Problem ist: Sind die Strings wirklich nur intern bei der Implementierung der Klasse verwendet oder werden sie an anderer Stelle verwendet.

Um wirklich pingelig zu sein, würde ich versuchen, die Schnittstelle der Klasse so sauber wie möglich zu halten, also wenn die Dateinamen-Strings für die "Außenwelt" nicht von Interesse sein sollten. Ich würde sie nur intern in der .cpp-Datei verstecken. Und in diesem Fall glaube ich nicht, dass ich mich mit dem Namespace befassen würde, sondern halte die Dinge einfach "statisch" (d. H. Innerhalb der .cpp-Datei). nur

2

Wenn in der Klasse der CPP-Datei verwendet wird, besteht keine Notwendigkeit, einen Namensraum jeglicher Art zu verwenden, einfach sagen:

const std::string f1 = "filename1"; 
const std::string f2 = "filename2"; 
const std::string f3 = "filename3"; 

Übermäßiger Einsatz von Namensräumen die neue Sache zu sein scheint - ich kann nicht persönlich die Attraktion sehen.

+1

Aber das kann Linker Fehler verursachen, wenn Namen f1, f2 usw. in anderen Kompilierungseinheiten sind. Aus diesem Grund existieren anonyme Namespaces. –

+0

Gibt es einen Unterschied zwischen diesen Definitionen und einem anonymen Namespace? Es sieht für mich aus, dass sie implizit als "statisch" definiert sind. – stone

+2

@Nemanja Nein, wird es nicht. Ein const-Objekt, das im Namespace-Bereich deklariert wird, ist lokal für die Übersetzungseinheit. –

0

Wie auch immer Sie es tun, eine Sache zu beachten: Ich würde nicht statische std :: string Objekte verwenden, sondern statische char * verwenden. Der Grund dafür liegt in möglichen Problemen mit der Reihenfolge der Initialisierung. Angenommen, Sie haben eine statische Instanz einer Klasse, deren Konstruktor auf die Zeichenfolge A::f1 verweist. Es gibt keine Garantie, dass A::f1 noch konstruiert wurde, und Sie werden einen Absturz oder schlimmer, keinen Absturz, sondern gefälschte Daten erhalten.

Fehler in der Reihenfolge der Initialisierung zu finden kann ziemlich unangenehm sein, und alles kann in einem Projekt gut aussehen, aber dann können Sie ein anderes Projekt mit denselben Bibliotheken erstellen, und die feinen Unterschiede in der Verknüpfungsreihenfolge verursachen diesen Fehler auf mysteriöse Weise erscheinen.

0

Haben Sie einfach die Const-Zeichenfolgen im Dateibereich in der Implementierungsdatei, ist der anonyme Namespace nicht notwendig, um ihre Verwendung auf diese Klasse zu beschränken.

C++ 003 Standard C.1.2 Satz 3: Grundbegriffe

Change: A name of file scope that is explicitly declared const, and not explicitly declared extern, has internal linkage, while in C it would have external linkage 

Hinweis: Der anonyme Namespace reduzieren hilft Namenskonflikte.