Probleme mit virtuellen funktionen



  • Hallo!
    Ich habe folgendes Problem:
    Ich habe einen Pointer auf ein Objekt, dessen Funktionalität ich während der Laufzeit ändern möchte. Er zeigt zunächst auf ein Objekt der Basisklasse, welches dann deleted werden soll und im Anschluss daran ein neues Objekt zugewiesen bekommen. also in etwa so:

    class base;
    class xt:public base;
    base *basePointer=new base();
    delete basePointer;
    basePointer=new xt();
    basePointer->doSomething();

    Wenn ich das versuche, schnallt das liebe Programm irgendetwas nicht und die vfptr-tabelle ist ungültig und somit wird die falsche virtuelle Funktion (die der base-klasse) ausgeführt.
    Ist an der vorgehensweise grundsätzlich etwas verkehrt/unsicher? Oder muss ich den Fehler woanders suchen und ich kann mit new und delete so umspringen wie im Beispiel?
    Danke und viele Grüße
    Sören



  • class base {
    public:
      virtual void doSomething() {cout<<"base"<<endl;}
    }; 
    class xt : public base {
    public: 
      void doSomething() {cout<<"xt"<<endl;} 
    }; 
    
    ...
    base *basePointer = new base; 
    delete basePointer; 
    
    basePointer = new xt; 
    basePointer->doSomething();
    

    genau so sollte es funktionieren.
    RTTI muss beim kompilieren aktiviert sein!!!



  • Ähhh, was ist RTTI?
    Muss in der xt-Klasse kein virtual stehen?
    Vielen Dank!
    Sören



  • Ok, weiss jetzt, was RTTI ist.
    In vielen Fällen habe ich schon einen pointer, der auf eine Basisklasse deklariert ist und dann ein abgeleitetes Objekt zugewiesen bekommt. Da gibt es auch keine Probleme. Die gibts nur, wenn ich vorher
    pt=new base()
    und dann
    delete pt;
    pt=new xt();
    mache.
    Es wird immer die Funktion der Baisklasse aufgerufen. Und das macht keinen Sinn für das Objekt...
    Grüße
    Sören



  • RTTI heißt RunTime Type Information, was soviel heißt wie: Zur Laufzeit ist der Typ bekannt. Braucht man aber eigentlich nur für dynamic_cast und typeid, nicht für virtuelle Funktionen.

    Und virtual muss nur in der Basisklasse angegeben werden, das "vererbt" sich praktisch 🙂

    e: Bist du sicher, dass du die Funktion als virtual deklariert hast?



  • soerenP schrieb:

    Ähhh, was ist RTTI?

    RunTimeTypeInformation. Auch wenn ich in diesem Fall nicht sehe, warum das aktiviert werden müsste. Nur das in der Basisklasse ein virtueller Destruktor sein sollte (Bei Basisklassen mit wenigen Ausnahmen sinnvoll)...

    soerenP schrieb:

    Muss in der xt-Klasse kein virtual stehen?

    Nein, das virtual wird "quasi" mit vererbt. Wichtig ist nur das es auf der untersten Ebene (in diesem Fall in der Klasse base) steht.



  • asc schrieb:

    soerenP schrieb:

    Ähhh, was ist RTTI?

    RunTimeTypeInformation. Auch wenn ich in diesem Fall nicht sehe, warum das aktiviert werden müsste. Nur das in der Basisklasse ein virtueller Destruktor sein sollte (Bei Basisklassen mit wenigen Ausnahmen sinnvoll)...

    soerenP schrieb:

    Muss in der xt-Klasse kein virtual stehen?

    Nein, das virtual wird "quasi" mit vererbt. Wichtig ist nur das es auf der untersten Ebene (in diesem Fall in der Klasse base) steht.

    hier muss es nicht aktiviert sein. sorry. ich meinte auch eher: es sollt ebei c++ eigentlich standarmäßig aktiviert sein...
    was den virtuellen destruktor anbelangt so sollte der bei jeder basisklasse als virtuell definiert werden (zumindest bei der allgemeinsten klasse). ansonsten löscht du beim delete *ptrBase nicht den "Teil" der abgeleiteten klasse.

    bitte benutz C/C++ Tags bei den Beiträgen, das liest sich leichter.
    SirAnn



  • soerenP schrieb:

    In vielen Fällen habe ich schon einen pointer, der auf eine Basisklasse deklariert ist und dann ein abgeleitetes Objekt zugewiesen bekommt. Da gibt es auch keine Probleme. Die gibts nur, wenn ich vorher

    pt=new base()
    und dann 
    delete pt; 
    pt=new xt();
    

    mache.
    Es wird immer die Funktion der Baisklasse aufgerufen. Und das macht keinen Sinn für das Objekt...

    Also ich habe mal ein Minibeispiel was eigentlich richtig funktionieren sollte:

    #include <iostream>
    
    class base
    {
    	public:
    		virtual void test()
    		{
    			std::cout << "base::test()\n";
    		}
    
    		virtual ~base()
    		{
    			std::cout << "base::~base()\n";
    		}
    };
    
    class child : public base
    {
    	public:
    		void test()
    		{
    			std::cout << "child::test()\n";
    		}
    
    		~child()
    		{
    			std::cout << "child::~child()\n";
    		}
    };
    
    int main()
    {
    	base* pBase = new base();
    	pBase->test();
    	delete pBase;
    
    	pBase = new child();
    	pBase->test();
    	delete pBase;
    
    	return 0;
    }
    

    cu André



  • Ok, vielen Dank für die Aufklärung!
    Es scheint so, als hätte das Problem sich verlagert 😕
    Auf jeden Fall wird (fragt mich nciht, was ich verändert habe!) jetzt immer die richtige Funktion aufgerufen.
    Sieht für mich wie ein tiefsitzendes Problem aus, das ständig seine Symptome wechselt 😞
    Ich danke euch auf jeden fall
    Sören



  • asc schrieb:

    ...RunTimeTypeInformation. Auch wenn ich in diesem Fall nicht sehe, warum das aktiviert werden müsste.

    muffmolch schrieb:

    hier muss es nicht aktiviert sein. sorry. ich meinte auch eher: es sollt ebei c++ eigentlich standarmäßig aktiviert sein...

    Jein, wenn ich es nicht brauche sehe ich keinen Grund warum ich es nicht deaktivieren kann, wenn gleich der Overhead wohl nicht so enorm ist (anders sieht es beim Exceptionhandling auf alten Compilern aus, wo ohne Einbau eines try/catch-blockes sich der Code bis zu 100% aufbläht - aus eigener Erfahrung).

    cu André



  • asc schrieb:

    Jein, wenn ich es nicht brauche sehe ich keinen Grund warum ich es nicht deaktivieren kann, wenn gleich der Overhead wohl nicht so enorm ist (anders sieht es beim Exceptionhandling auf alten Compilern aus, wo ohne Einbau eines try/catch-blockes sich der Code bis zu 100% aufbläht - aus eigener Erfahrung).cu André

    okay, ich gebe mich geschlagen. aber als anfänger läuft man mit aktivierter RTTI nicht in Probleme, die ausschließlich etwas mit der RTTI zu tun haben...


Anmelden zum Antworten