Ergebnis 1 bis 2 von 2

[C++]globale const durch Funktion belegen

  1. #1 Zitieren
    Deus Avatar von Oparilames
    Registriert seit
    May 2004
    Ort
    ex contrariis
    Beiträge
    11.015
    Hallo,

    kann mir kurz jemand sagen, ob es eine bessere Möglichkeit gibt, um ein
    const int anzulegen, welches global sichtbar ist und erst durch den Return-
    wert einer Funktion belegt wird?
    Der Beispielcode funktioniert bei mir, aber ich versuche ihn in mein
    derzeitiges Projekt zu integrieren erhalte ich lauter [i]undefined reference
    to `STR_LOGFILENAME'
    [i]-Meldungen.


    Dieser Code verdeutlich, was ich möchte und ist lauffähig.
    Code:
    #include <iostream>
    #include <string>
    #include <vector>
    extern const int STR_LOGFILENAME;
    
    class cLogStrMan
    {
        private:
            std::vector<std::wstring> txt;
        public:
            const int addString(std::wstring c);
            cLogStrMan();
    };
    
    cLogStrMan MrStr;
    
    void initStrings()
    {
        const int STR_LOGFILENAME=MrStr.addString(L"Game.Log");
    }
    
    const int cLogStrMan::addString(std::wstring c){
        txt.emplace_back(c);
        return txt.size();
    }
    
    cLogStrMan::cLogStrMan(){
        initStrings();
        for(auto i: txt)
            std::wcout << i << std::endl;
    }
    
    int main()
    {
        std::cin.get();
    }
    Kann es daran liegen, dass ich dort die Stellen in erschiedenen Datein
    habe und entsprechen mit #include arbeite?

    Edit:-> Fehlerquelle gefunden. Aber wie löse ich es?
    Dieser Code ist nicht kompilierbar.
    Code:
    #include <iostream>
    #include <string>
    #include <vector>
    extern const int STR_LOGFILENAME;
    
    class cLogStrMan
    {
        private:
            std::vector<std::wstring> txt;
        public:
            const int addString(std::wstring c);
            cLogStrMan();
    };
    
    
    class object
    {
        public:
        int peter(){
            return STR_LOGFILENAME;
        };
    };
    
    object hallo;
    cLogStrMan MrStr;
    
    void initStrings()
    {
        const int STR_LOGFILENAME=MrStr.addString(L"Game.Log");
    }
    
    const int cLogStrMan::addString(std::wstring c){
        txt.emplace_back(c);
        return txt.size();
    }
    
    cLogStrMan::cLogStrMan(){
        initStrings();
        for(auto i: txt)
            std::wcout << i << std::endl;
    }
    
    int main()
    {
        MrStr;
        hallo.peter();
        std::cin.get();
    }
    Oparilames nachdem er seinen Gesellenbrief erhalten hat:
    »Das war's mit dir, du Mistvieh!«
    Oparilames ist offline Geändert von Oparilames (08.08.2015 um 11:36 Uhr)

  2. #2 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.383
    Zitat Zitat von Oparilames Beitrag anzeigen
    Hallo,

    kann mir kurz jemand sagen, ob es eine bessere Möglichkeit gibt, um ein
    const int anzulegen, welches global sichtbar ist und erst durch den Return-
    wert einer Funktion belegt wird?
    Konstanten müssen bereits während ihrer Deklaration einen Wert zugewiesen bekommen, was ebenso für globale Konstanten gilt. Was du forderst, wäre also keine Konstante.
    Konstanten innerhalb von Klassen könnten den Eindruck erwecken, dass es dort anders liefe. Dem ist aber nicht so, weil die Zuweisung eines Wertes an die Konstante mit der Initialisierung zusammenfällt. Vor seiner Initialisierung existiert das Objekt nämlich nicht.

    Der Beispielcode funktioniert bei mir, aber ich versuche ihn in mein
    derzeitiges Projekt zu integrieren erhalte ich lauter [i]undefined reference
    to `STR_LOGFILENAME'
    [i]-Meldungen.
    Du hast zumindest innerhalb dieser Datei kein globales STR_LOGFILENAME definiert. Falls dieses nicht woanders geschehen ist, dann bleibt STR_LOGFILENAME undefiniert, weshalb wohl dein Linker (nicht dein Compiler) seine Arbeit nicht fortsetzen kann und sich entsprechend beschwert, was hier sehr aussagekräftig erfolgt, indem er mitteilt, dass es zu dem Verweis auf STR_LOGFILENAME keine Definition gibt. Dieser Verweis ("reference") ist hier nicht im Sinne von (T &) zu verstehen, sondern als ein Symbolverweis, welchen der Compiler für den Linker im Objektcode anlegt, einmal je Import (wie hier) und insgesamt genau einmal für den Export der Definition (welche wohl fehlen dürfte, weshalb der Linker das Symbol vergeblich sucht, denn der Compiler konnte mangels Definition keines für ihn anlegen) im zugehörigen Modul (was bei dir wohl durch dein "sehr spezielles" Inkludierungsschema alles ein und dasselbe ist). Das Keyword extern bedeutet, dass sich die Definition in einem anderen Modul befindet, weshalb der Compiler sich erst mal trotz fehlender Definition zufrieden gibt und ein Symbol für den Import anlegt. Wenn der Linker jedoch keinen dementsprechenden Export findet, dann bricht der Linkerprozess (üblicherweise mit Fehlermeldung) ab.


    Code:
    void initStrings()
    {
        const int STR_LOGFILENAME=MrStr.addString(L"Game.Log");
    }
    Es handelt sich hier bei STR_LOGFILENAME um eine eigenständige lokale Variable, welche lediglich den Namen der globalen verdeckt und nichts mit dieser zu tun hat.
    Unabhängig davon: Nein, man kann keine globalen Variablen innerhalb von Funktionen definieren, nicht mal, wenn man extern voranstellen würde.
    Der Rückgabewert wirkt sich hier nicht aus. Optimierende Compiler sind üblicherweise in der Lage, das wegzuoptimieren, als hättest du gleich dieses geschrieben:
    Code:
    void initStrings()
    {
        MrStr.addString(L"Game.Log");
    }


    Code:
    const int cLogStrMan::addString(std::wstring c){
        txt.emplace_back(c);
        return txt.size();
    }
    Der const-Qualifizierer bezüglich des Rückgabewertes wirkt sich nicht aus, da es sich um einen rvalue, genauer, einen prvalue, handelt. Es existiert also kein Objekt, auf welches man zugreifen könnte, geschweige denn, modifizierend. Das int gibt lediglich an, dass der Rückgabewert von diesem Typ ist, und nicht etwa, dass ein int im Speicher reserviert würde. Und was nicht ist, kann man nicht modifizieren.

    Kann es daran liegen, dass ich dort die Stellen in erschiedenen Datein
    habe und entsprechen mit #include arbeite?
    Nein, es sei denn, dein Linker hätte noch weitere Fehlermeldungen ausgespuckt, von denen wir nichts wissen oder du hättest zyklische Includes fabriziert, was durchaus sein kann. Vermutlich fehlt aber einfach die Definition von STR_LOGFILENAME, s.o.

    Code:
    Edit:-> Fehlerquelle gefunden. Aber wie löse ich es?
    Dieser Code ist nicht kompilierbar.
    Nein, leider noch nicht gefunden, es handelt sich nach wie vor um dasselbe Problem, s.o. Ich erlaube mir mal einige Anmerkungen:
    Code:
    // An sich korrekt, aber wo ist STR_LOGFILENAME definiert?
    // Falls nirgends definiert, bekommst du eine Fehlermeldung vom Linker (nicht vom Compiler), s.o.
    extern const int STR_LOGFILENAME;  // irritierender Name für einen int
    
    class cLogStrMan
    {
        private:
            std::vector<std::wstring> txt;
        public:
            // const wirkungslos
            const int addString(std::wstring c);  // Du könntest evtl. einen (const wchar_t*) nehmen, s.u.
            cLogStrMan();
    };
    
    
    class object
    {
        public:
        int peter(){
            return STR_LOGFILENAME;  // könnte man machen, wenn STR_LOGFILENAME definiert wäre
        };
    };
    
    object hallo;
    cLogStrMan MrStr;
    
    void initStrings()
    {
        const int STR_LOGFILENAME=MrStr.addString(L"Game.Log");  // lokale Variable sowie const wirkungslos, s.o.
    }
    
    // const wirkungslos, s.o.
    const int cLogStrMan::addString(std::wstring c){  // Du könntest einen (const wchar_t*) nehmen...
        txt.emplace_back(c);  // ...und ihn hier zwecks "In-Place-Construction" übergeben.
        return txt.size(); 
    }
    
    cLogStrMan::cLogStrMan(){
        initStrings();
        for(auto i: txt)
            std::wcout << i << std::endl;
    }
    
    int main()
    {
        MrStr;  // wirkungsloser Ausdruck, Compiler sollte das melden.
    
        hallo.peter();
        std::cin.get();
    }
    jabu ist offline Geändert von jabu (09.08.2015 um 12:44 Uhr)

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •