Fehler: undefined reference to `vtable for CObject'



  • Hallo!

    Ich hab da ein kleines Problem beim erstellen eines Projekts.
    Da wären ein paar Klassen: Die Grundklasse CObject:

    class CObject
    {
     protected:
      GtkWidget*    pWidget;
    
     public:
      CObject() { }
      ~CObject() { }
    
      GtkWidget*    GetWidget();
    
      virtual void  Create()=0; // erstellt Widget
    
      void          Show();   // Zeigt Widget an
    };
    

    Und eine davon abgeleitete Klasse CWindow:

    class CWindow : public CObject
    {
     private:
      string        szTitle;        // Name des Fensters
      gint          iWidth;         // Breite
      gint          iHeight;        // Höhe d. Fensters
    
     public:
      CWindow();
      ~CWindow();
    
      string        GetTitle();     // Titel des Fensters
      gint          GetWidth();     // Breite
      gint          GetHeight();    // Höhe
    
      void          SetTitle(string str); // Titel des Fensters setzen
      void          SetDimensions(gint w, gint h); // Setzt Höhe und Breite
    
      void          Create();       // Erstellt das Fenster
    };
    

    Die Hauptdatei sieht so aus:

    #include <stdlib.h>
    #include <gtk/gtk.h>
    #include "window.h"
    
    int main(int argc, char* argv[])
    {
            gtk_init(&argc,&argv);
    
            CWindow hWindow;
    
            hWindow.SetTitle("Hello World!");
            hWindow.Create();
            hWindow.Show();
    
            gtk_main();
    
            return 0;
    }
    

    Wenn ich nun meine Makefile ausführe, die so aussieht...

    # VARIABLEN ===========================================//
    CC      = g++
    FLAGS   = `pkg-config --cflags --libs gtk+-2.0`
    OBJ     = player.o window.o object.o
    
    # REGELN UND ABHÄNGIGKEITEN ===========================//
    
    # alle Objektedateien zum Programm linken
    all: $(OBJ)
            $(CC) -g -o player $(OBJ) $(FLAGS)
    
    # Alle O-Datei hängen von entsprechenden cpp-Dateien ab!
    %.o: %.cpp
            $(CC) $(FLAGS) -c $<
    

    ...dann bekomme ich folgende Fehlermeldung:

    g++ -g -o player player.o window.o object.o `pkg-config --cflags --libs gtk+-2.0`
    window.o(.gnu.linkonce.t._ZN7CObjectC2Ev+0x8): In function CObject::CObject[not-in-charge]()': : undefined reference tovtable for CObject'
    window.o(.gnu.linkonce.t._ZN7CObjectD2Ev+0x8): In function CObject::~CObject [not-in-charge]()': : undefined reference tovtable for CObject'
    window.o(.gnu.linkonce.r._ZTI7CWindow+0x8): undefined reference to `typeinfo for CObject'
    collect2: ld returned 1 exit status
    make: *** [all] Fehler 1

    Ich weiß echt nicht wo der Fehler liegt! Vielleicht ist es zu lange her, dass ich C++ programmiert habe und deswegen finde ich den Fehler nicht. Kann jemand von euch mir sagen wo der Fehler liegt?



  • Kann es sein, dass CObject Create() nicht implementiert ist?



  • mach mal den destruktor von CObject virtual...

    auf bald
    oenone



  • @Ponto

    Ja, virtual void CObject::Create() ist nicht implementiert. Es ist aber auch eine virtuelle Funktion. Leider habe ich vergessen zu schreiben: Create()=0;
    Wie auch immer, ich habe den Code unten um diese Änderung aktualisiert.

    Die Fehlermeldung hat sich jedoch nicht wesentlich verändert:

    g++ -g -o player player.o window.o object.o `pkg-config --cflags --libs gtk+-2.0`
    window.o(.text+0xe): In function CWindow::CWindow[not-in-charge]()': : undefined reference toCObject::CObject[not-in-charge]()'
    window.o(.text+0x87): In function CWindow::CWindow[not-in-charge]()': : undefined reference toCObject::~CObject [not-in-charge]()'
    window.o(.text+0xb0): In function CWindow::CWindow[in-charge]()': : undefined reference toCObject::CObject[not-in-charge]()'
    window.o(.text+0x129): In function CWindow::CWindow[in-charge]()': : undefined reference toCObject::~CObject [not-in-charge]()'
    window.o(.text+0x175): In function CWindow::~CWindow [not-in-charge]()': : undefined reference toCObject::~CObject [not-in-charge]()'
    window.o(.text+0x191): In function CWindow::~CWindow [not-in-charge]()': : undefined reference toCObject::~CObject [not-in-charge]()'
    window.o(.text+0x1cf): In function CWindow::~CWindow [in-charge]()': : undefined reference toCObject::~CObject [not-in-charge]()'
    window.o(.text+0x1eb): In function CWindow::~CWindow [in-charge]()': : undefined reference toCObject::~CObject [not-in-charge]()'
    window.o(.gnu.linkonce.r._ZTI7CWindow+0x8): undefined reference to `typeinfo for CObject'
    collect2: ld returned 1 exit status
    make: *** [all] Fehler 1

    Auch ein virtueller Destruktur hatte keine Besserung zur Folge (eigentlich gar keinen Effekt). 😞



  • Sind alle Methoden von CObject implementiert, die nicht abstrakt sind?



  • object.cpp:

    #include "object.h"
    
    void CObject::Show()
    {
            gtk_widget_show(pWidget);
    }
    
    GtkWidget* CObject::GetWidget()
    {
            return pWidget;
    }
    

    Also, ja. 😕



  • Kannst du den Code vielleicht zusammengepackt auf eine Seite stellen?



  • Kommt sofort!:

    player.cpp (Hauptdatei):

    #include <stdlib.h>
    #include <gtk/gtk.h>
    #include "window.h"
    
    int main(int argc, char* argv[])
    {
            gtk_init(&argc,&argv);
    
            CWindow hWindow;
    
            hWindow.SetTitle("Hello World!");
            hWindow.Create();
            hWindow.Show();
    
            gtk_main();
    
            return 0;
    }
    

    window.h

    #ifndef _WINDOW_H_
    #define _WINDOW_H_
    
    /*
       CWindow, Standart-Fensterklasse
    
       @2004 - Mathias Kahl     LastChange: 23. Dezember 2004
    */
    
    #include <stdlib.h>
    #include <string>
    #include <gtk/gtk.h>
    #include "object.h"
    
    using namespace std;                                                               
    
    class CWindow : public CObject
    {
     private:
      string        szTitle;        // Name des Fensters
      gint          iWidth;         // Breite
      gint          iHeight;        // Höhe d. Fensters
    
     public:
      CWindow();
      ~CWindow();
    
      string        GetTitle();     // Titel des Fensters
      gint          GetWidth();     // Breite
      gint          GetHeight();    // Höhe
    
      void          SetTitle(string str); // Titel des Fensters setzen
      void          SetDimensions(gint w, gint h); // Setzt Höhe und Breite
    
      void          Create();       // Erstellt das Fenster, basierend auf private
    };
    
    #endif
    

    window.cpp

    #include "window.h"
    
    // CONSTRUCTOR & DESTRUCTOR ----------------------//
    
    CWindow::CWindow()
    {
            szTitle = "CWindow";
            iWidth = iHeight = 200;
    }
    
    CWindow::~CWindow()
    {
    
    }
    
    // GETTER --------------------//
    
    string  CWindow::GetTitle() { return szTitle; }
    gint    CWindow::GetWidth() { return iWidth; }
    gint    CWindow::GetHeight() { return iHeight; }
    
    // SETTER  -------------------//
    
    void CWindow::SetTitle(string str)
    {
            pWidget = NULL;
            szTitle = str;
            gtk_window_set_title(GTK_WINDOW(pWidget), str.c_str() );
    }
    
    void CWindow::SetDimensions(gint w, gint h)
    {
            iWidth = w;
            iHeight = h;
    }
    
    //  ---------------------------------//
    
    void CWindow::Create()
    {
            if(pWidget != NULL) return;
            pWidget = gtk_button_new_with_label(szTitle.c_str() );
    }
    

    object.h

    #ifndef _OBJECT_H_
    #define _OBJECT_H_
    
    /*
       Grundklasse für GTK-Widgets. Fasst grundlegende Eigenschaften
       zusammen.
    
       @2004 - Mathias Kahl         Last Change: 23. Dezember 2004
    */
    
    #include <stdlib.h>
    #include <gtk/gtk.h>
    
    class CObject
    {
     protected:
      GtkWidget*    pWidget;
    
     public:
      CObject() { }
      virtual ~CObject() { }
    
      GtkWidget*    GetWidget();
    
      virtual void  Create()=0; // erstellt Widget
    
      void          Show();   // Zeigt Widget an
    };
    
    #endif
    

    object.cpp

    #include "object.h"
    
    void CObject::Show()
    {
            gtk_widget_show(pWidget);
    }
    
    GtkWidget* CObject::GetWidget()
    {
            return pWidget;
    }
    

    Die Makefile findest du in meinem ersten Posting.



  • 1. Das ganze kompiliert und linkt ohne Probleme. Hast du mal alles clean gemacht und neu kompiliert?
    2. #include <cstdio> ist besser
    3. #ifndef WINDOW_H_ is besser als #ifndef _WINDOW_H_, da Namen, die mit einem Unterstrich anfangen für dich tabu sind.
    4. Gtk is eine C library. Deshalb:

    extern "C" {
    #include <gtk/gtk.h>
    }
    

    5. Das folgende Makefile gefaellt mir besser:

    # VARIABLEN ===========================================// 
    CC      = g++ 
    CFLAGS   = `pkg-config --cflags  gtk+-2.0` 
    LDFLAGS = `pkg-config  --libs gtk+-2.0` 
    OBJ     = player.o window.o object.o 
    
     # REGELN UND ABHÄNGIGKEITEN ===========================// 
    
     # alle Objektedateien zum Programm linken 
    all: $(OBJ) 
     $(CC) -g -o player $(OBJ) $(LDFLAGS) 
    
     # Alle O-Datei hängen von entsprechenden cpp-Dateien ab! 
    %.o: %.cpp 
     $(CC) $(CFLAGS) -c $<
    


  • Hey, vielen Dank!

    Es scheint wirklich an der Makefile gelegen zu haben.
    Zu einem habe ich "vergessen" nach dem Kompilieren sauber zu machen, und zum anderen war die Makefile falsch. Nachdem ich mit meiner alten Makefile nochmals kompilierte waren klarere Fehlermeldungen das Ergebnis, dann mit den Änderungen an der Makefile hats geklappt. Ich bin dir wirklich sehr dankbar!!

    Also nochmal vielen Dank an alle und speziell an Ponto! 👍


Anmelden zum Antworten