Ableitung "nicht definiert"?



  • Kannst du den genauen Code zeigen der den Fehler produziert?

    PS:
    wenn es um meinen Code gehen sollte, du musst immer module_iterator<IModule> returnen. Du wandelst den nur im Client Code dann zu einem module_iterator<CModule> um.



  • Hi.
    Es handelt sich um diesen "kleinen" Abschnitt:

    class IScript
    {
    public:
        // ...
        virtual IModule *GetMainModule() const = 0; // entspricht Zeile 10 aus dem Fehler
    };
    
    class CScript : public IScript
    {
    public:
        // ...
        virtual CModule *GetMainModule() const // entspricht Zeile 22 aus dem Fehler
        {
            return this->m_pMainModule;
        }
    
    private:
        // ...
        CModule *m_pMainModule;
    };
    

    Hier noch der Code von CModule und IModule:

    class IModule
    {
    public:
        // ...
    };
    
    class CModule : public IModule
    {
    public:
        // ...
    
    private:
        // ...
    };
    

    Der genaue Fehler ist:

    1><Pfad>\CScript.hpp(22) : error C2555: 'CScript::GetMainModule': Der überschreibende virtuelle Funktionsrückgabetyp unterscheidet sich und ist keine 'covariant' von 'IScript::GetMainModule'
    1>        <Pfad>\IScript.hpp(10): Siehe Deklaration von 'IScript::GetMainModule'
    

    Gruß



  • Du hast alles richtig gemacht, es ist aber ein Bug im Compiler:
    http://support.microsoft.com/kb/240862



  • Oh man, das heißt, dass ich das nicht fixxen kann?
    Nervt ja übelst.

    Aber da steht gar nichts von MS VC++ 2008, nur von älteren Versionen. Komisch...

    Gruß und Danke



  • theliquidwave schrieb:

    Oh man, das heißt, dass ich das nicht fixxen kann?
    Nervt ja übelst.

    Du kannst entweder auf die Covarianz verzichten oder aber eine template Funktion verwenden um den Cast zu automatisieren.

    Aber da steht gar nichts von MS VC++ 2008, nur von älteren Versionen. Komisch...

    Keine Ahnung. Dein Code ist korrekt, mehr kann ich nicht sagen.



  • Hi...
    Mir ist gerade aufgefallen, dass genau das gleiche Problem an einer anderen Stelle nicht auftritt:

    class IScript
    {
    public:
        // ...
    
    private:
        // ...
    };
    
    class CScript : public IScript
    {
    public:
        // ...
    
    private:
        // ...
    };
    
    class IModule
    {
    public:
        virtual IScript *GetScript() const = 0;
        // ...
    };
    
    class CModule : public IModule
    {
    public:
        virtual CScript *GetScript() const; // hier kracht gar nichts
        // ...
    
    private:
        CScript *m_pScript;
    };
    

    Theoretisch müsste es dort doch genau so krachen, tut es aber nicht o_O
    Woran könnte das liegen? Mir fällt dazu echt nichts mehr ein...

    Gruß


  • Administrator

    Ich denke, dass ich dein Problem kenne. Allerdings warst du wahrscheinlich nicht ganz ehrlich mit uns. Dein tatsächlicher Code sieht nämlich so aus:

    class IModule 
    { 
    public: 
        // ... 
    }; 
    
    // ... 
    
    class IScript 
    { 
    public: 
        // ... 
        virtual IModule *GetMainModule() const = 0;
    }; 
    
    // ... 
    
    class CModule; // Vorwärtsdeklaration
    
    class CScript : public IScript 
    { 
    public: 
        // ... 
        virtual CModule *GetMainModule() const;
    
    private: 
        // ... 
        CModule *m_pMainModule;
    };
    
    // ...
    
    class CModule : public IModule 
    { 
    public: 
        // ... 
    
    private: 
        // ... 
    };
    

    Für die Kovarianz reicht eine Vorwärtsdeklaration nicht, weil der Kompiler dann nicht erkennen kann, dass CModule von IModule erbt.

    Grüssli



  • Stimmt -.-
    Habe ich echt total vergessen, bitte vergebt mir 😃

    Komisch ist aber, dass ich IModule, CModule, CScript und IScript ebenfalls "vorwärts" deklariere.
    Eine Vorwärtsdeklaration wie class CModule : public IModule; funktioniert nicht.

    Gibt es dafür andere Lösungen? Denn ohne Vorwärts-Deklaration würde das ganze nicht mehr funktionieren.
    Entweder das ist ein Design-Fehler meinerseits, oder es geht einfach nicht anders (ich vermute ersteres), hätte aber auch keine Idee, wie ich es anders lösen könnte.

    Gruß



  • Dravere schrieb:

    Dein tatsächlicher Code sieht nämlich so aus

    👍 Nice one
    Den Fehler wuerde ich ewig suchen.

    @theliquidwave:
    Warum brauchst du denn die Gegenseitige Forward Deklaration?
    Fuer die Covarianz reicht es ja wenn CModule in CScript bekannt ist - in den anderen Dateien kannst du ja immernoch Forwarden.

    uU reicht ein pimpl-Idiom an anderer Stelle aus um die notwendigen Forwards zu reduzieren?



  • Das würde nicht funktionieren, da ich in den Headerdateien bereits CModule deklarieren muss, da der Compiler sonst meckert. Es würde also auch nichts bringen die Deklaration in die C++-Datei zu packen 😕

    Mit pimpl-Idiom meinst du "Opaque pointers"? Also so wie ich das verstanden habe, das einfache benutzen von void* anstatt CModule* in den Headerdateien? Dann könnte ich auch gleich IModule* benutzen.

    Gruß



  • theliquidwave schrieb:

    Das würde nicht funktionieren, da ich in den Headerdateien bereits CModule deklarieren muss, da der Compiler sonst meckert. Es würde also auch nichts bringen die Deklaration in die C++-Datei zu packen 😕

    Ich glaube da reden wir aneinander vorbei.

    Mit pimpl-Idiom meinst du "Opaque pointers"? Also so wie ich das verstanden habe, das einfache benutzen von void* anstatt CModule* in den Headerdateien? Dann könnte ich auch gleich IModule* benutzen.

    Nein. Du versteckst mit PImpl lediglich die Implementierung und die privaten Daten. Der Punkt aber ist: du versteckst die privaten Daten.

    Warum braucht CModule eine Forward deklaration fuer CScript? zB weil CModule einen Zeiger auf das CScript besitzt dem es gehoert. Mit PImpl wuerdest du nun diesen Zeiger auslagern in die Implementations Datei und somit kein Forward mehr fuer CScript in der normalen cmodule.hpp Datei brauchen.

    Es kann natuerlich andere Grunde geben warum CModule CScript kennen muss. Wenn zB CScript direkt in der Interfacedefinition von CModule vorkommt ist das natuerlich unpraktikabel. Deshalb war ja die Frage: warum muss CModule CScript schon in der *.hpp Datei kennen.



  • Naja, damit eben der Compiler CModule kennt. Das liegt daran, dass mehrer Headerdateien sich gegenseitig includen; naja. Wenn ich die Includereihenfolge verändere (also Module vor Script include), dann kommt der Fehler den ich ganz oben auf dieser Seite eigentlich erwartet hätte, dieser Fehler wäre aber weg. Ein Katz und Maus Spiel 😕

    Gruß


Anmelden zum Antworten