[solved] [gcc] Linker-Fehler 'Undefined reference to vtable'



  • Hallo,

    habe zu o.g. Fehler auch mit der SuFu nichts (in diesem Forum) gefunden, die Erklärungen, die Google lieferte, versteh ich so nicht richtig...

    Also, ich habe ein Beispiel aus einem C++-Buch versucht, zu übersetzen, in dem alle Memberfunktionen von (virtuellen) Klassen inline definiert werden:

    [...]
    
    class Document {
      public:
        Document(const string& name) { m_name = name; }
        virtual ~Document() { }
        virtual void Open() = 0;
        virtual void Close() = 0;
        string GetName() { return m_name; }
      private:
        string m_name;
    };
    
    class MyDocument : public Document {
      public:
        MyDocument(const string& name) : Document(name) { }
        virtual ~MyDocument() { }
        void Open() { cout << "MyDocument::Open(" << GetName() << ")" << endl; }
        void Close() { cout << "MyDocument::Close(" << GetName() << ")" << endl; }
    };
    
    [...]
    

    Wenn ich das Programm mit dem o.g. Teil übersetze, läuft beim gcc alles durch, der Linker beschwert sich dann aber:

    undefined reference to 'vtable for MyDocument'

    Auf der Suche nach einer Erklärung fand ich bsp.w. die folgende:

    That is the most obscure error message the gcc produces, but the reason
    is usually simple:

    The compiler has to put the vtable into an object file. It puts it into
    the object file where the definition of the first non-inline member
    function is. If it is missing, you get this rather unhelpful linker
    error. Please check the existence of the definitions of your member
    functions.

    D.h., der gcc muss die vtable in irgendeine Objektdatei packen, nach o.g. Angabe in das Objektfile mit der ersten nicht-inline Member-Funktion. In o.g. Bsp. existieren aber keine nicht-inline-Funktionen 😕

    Wie lässt sich o.g. Code mit dem gcc übersetzen/linken ?

    Danke für alle Hinweise/Tipps,
    AlGaN



  • So wie ich das verstehe, darfst Du den Code nicht *inline* schreiben!
    (Sehr misteriös...)



  • Der GCC packt wie der Auszug besagt seine Virtual Table an die Stelle, an der auch die Implementierung der ersten virtuellen Funktion der Klasse auftaucht. Diese darf allerdings nicht inline sein, da diese einmalig sein muss (ODR).

    Das bedeutet wohl, dass eine polymorphe Klasse ohne nicht-inline Funktionen beim gcc keine Virtual Table hat, bzw. keine bekommt weil der Compiler nicht weiss in welches Objekt er sie packen soll. Da die Inline-Funktionen in jeder ÜE vorhanden sind, kann er sich nicht "zufällig" eine aussuchen.

    Versuch mal, den Körper des Destructors in ein Implementationsfile zu legen, statt inline.



  • Ein sehr seltsamer Compiler/Linker... der VC8 kompiliert/linkt das ohne Probleme... 🤡



  • Hallo,

    ok, ich habe eine 'Dummy'-Implementierungsdatei mit folgendem Inhalt erstellt:

    [...]
    // non-inlines
    Document::~Document() { }
    
    MyDocument::~MyDocument() { }
    [...]
    

    Da gibt's vom gcc keine Beanstandungen mehr, es scheint also wirklich so zu sein, dass virtuelle Funktionen nur inline nicht funktioniert beim gcc... 🙄 (will mir jetzt lieber nicht überlegen, warum das intern so geregelt ist)

    Danke für alle Hinweise & Gruss,
    AlGaN


Anmelden zum Antworten