static const



  • Hi,
    ich habe im Moment ein merkwürdiges Problem:
    Zunächst habe ich eine Singleton-Klasse die im Konstruktor einige Konstanten aus einer Datei lädt und in einer std::map speichert.
    Jetzt will ich an anderer Stelle im Programm damit einige oft benötigte Konstanten initialisieren und danach auch nicht mehr ändern.
    Merkwürdigerweise kann ich zur Initialisierung der Konstante eine Methode des Singletons aufrufen bevor der Singleton-Konstruktor ausgeführt wurde?! 😮 Das äußert sich natürlich in falschen Werten für die Konstanten, da sie noch nicht in der std::map vorhanden sind.
    Ansonsten arbeiten alle Methoden einwandfrei, also wenn der Konstruktor einmal ausgeführt wurde.

    Hat jemand eine Idee wie das Zustande kommt?

    Ich habe auch mal testweise einfach das "const" bei der Konstante weggelassen, das ändert auch nichts. Es mag ja sein das man Konstanten nicht auf diese weise initialisieren soll, aber warum läßt der Compiler das dann zu?

    CConfigNode.h:

    class CConfigNode {
    public:
        // ...
        static const uint16 CN_ID_FILEROOT;  // hier ist die Konstante
        // ...
    };
    

    CConfigNode.cpp:

    #include "CConfigNode.h"
    // ...
    // initialisierung der Konstante
    const uint16 CConfigNode::CN_ID_FILEROOT = CConfigNameTable::getInstance().getIdFromName("fileroot");
    // ...
    

    CConfigNameTable.h:

    // das Singleton
    class CConfigNameTable {
    public:
        // ...
        static const CConfigNameTable& getInstance() { return instance; }
    
        uint16 getIdFromName(const std::string& sName) const;
    private:
        // ...
        static CConfigNameTable instance;
    };
    

    Dank im voraus,
    Coolcat

    P.S.:
    Falls wichtig:
    Compiler: GCC 4.1.1 / FC5 Linux / Kernel: 2.6.17-1.2187_FC5



  • Eine statische Memberfunktion kann doch ohne vorhandenes Objekt ausgeführt werden. Warum sollte der Compiler bei dir meckern?
    Ich würde das Singleton sowieso ein wenig anders machen, so dass der Aufruf von getInstance auch den Konstruktor aufruft (beim ersten Mal). Das kann man machen, indem du nicht eine Referenz, sondern einen Pointer zurückgibst und den bei Bedarf mit new erstellst.
    Wie erstellst du denn dein instance?



  • Sry, vergessen:

    CConfigNameTable.cpp

    CConfigNameTable CConfigNameTable::instance = CConfigNameTable();
    

    Eine statische Memberfunktion kann doch ohne vorhandenes Objekt ausgeführt werden.

    Klar, aber getIdFromName() ist nicht statisch. 😕

    Coolcat



  • Aber getInstance() ist static.



  • Hm, hab es auf deinen Rat hin jetzt so gelöst:

    class CConfigNameTable {
    public:
        static const CConfigNameTable& getInstance() {
            static CConfigNameTable instance = CConfigNameTable();
            return instance;
        }
        // ...
    };
    

    das funktioniert. 🙂

    Ich verstehe allerdings immer noch nicht warum das andere nicht funktionierte.

    Coolcat



  • Coolcat schrieb:

    Hm, hab es auf deinen Rat hin jetzt so gelöst:

    So reicht auch, sonst hast Du eine unerwünschte Copyconstruction aus einem Temporary (oder?!). Letzteres würde aber auch verhindert wenn Du den Konstruktor des Singletons private machen würdest.

    class CConfigNameTable {
    public:
        static const CConfigNameTable& getInstance() {
            static CConfigNameTable instance;
            return instance;
        }
    };
    

    Ich verstehe allerdings immer noch nicht warum das andere nicht funktionierte.

    Weil die Initialisierungsreihenfolge von statischen Objekten auf File-Scope nicht garantiert ist. Will heissen es könnte sein dass die statischen Member von CConfigNode initialisiert werden bevor das statische Member instance von CConfigNameTable initialisiert wurde. Statische Objekte in Funktions-Scope werden hingegen beim ersten Aufruf der Funktion initialisiert, und Du hast so eine definierte Initialisierungsreihenfolge.



  • So reicht auch, sonst hast Du eine unerwünschte Copyconstruction aus einem Temporary (oder?!)

    Ich denke doch das der Compiler schlau genug ist das zu erkennen. Naja, ich habs trotzdem mal geändert. :p

    Will heissen es könnte sein dass die statischen Member von CConfigNode initialisiert werden bevor das statische Member instance von CConfigNameTable initialisiert wurde.

    Ok, das reicht mir 🙂

    thx @ all

    Coolcat


Anmelden zum Antworten