Basis Klasse in Abgeleitete Klasse umwandeln



  • Wenn du Polymorphie verwendest, kannst du in der Liste Zeiger auf die Basisklasse speichern. Die Zeiger können dann sowohl auf Basisklasse als auch auf abgeleitete Klassen zeigen - je nach Objekt werden die passenden virtuellen Funktionen aufgerufen.



  • Nexus schrieb:

    Wenn du Polymorphie verwendest, kannst du in der Liste Zeiger auf die Basisklasse speichern. Die Zeiger können dann sowohl auf Basisklasse als auch auf abgeleitete Klassen zeigen - je nach Objekt werden die passenden virtuellen Funktionen aufgerufen.

    Es gibt nur die virtuellen Funktionen, die die Basisklasse anbietet. Und diese Funktionen rufen dann die Funktionen der abgeleiteten Klasse auf.
    Wenn du die nicht-virtuellen Funktionen einer abgeleiteten Klasse haben willst, kommst du um einen Downcast nicht herum, was aber wie schon gesagt eher schlechtes Design ist, wenn du das machen musst. (Mal abgesehen davon, dass man sich auch recht ins Bein schiessen kann).



  • drakon schrieb:

    Es gibt nur die virtuellen Funktionen, die die Basisklasse anbietet.

    Hab ich mich so unklar augedrückt? 😉

    Mit "passenden virtuellen Funktionen" meinte ich natürlich virtuelle Funktionen, die in der Basisklasse deklariert worden sind und bei denen für jedes Objekt die passende Version (also die dem Objekt zugehörige) aufgerufen wird.



  • Nexus schrieb:

    drakon schrieb:

    Es gibt nur die virtuellen Funktionen, die die Basisklasse anbietet.

    Hab ich mich so unklar augedrückt? 😉

    Mit "passenden virtuellen Funktionen" meinte ich natürlich virtuelle Funktionen, die in der Basisklasse deklariert worden sind und bei denen für jedes Objekt die passende Version (also die dem Objekt zugehörige) aufgerufen wird.

    Ja, ich finde du hast einen, ein wenig unglücklichen Satz gewählt..

    Die Zeiger können dann sowohl auf Basisklasse als auch auf abgeleitete Klassen zeigen - je nach Objekt werden die passenden virtuellen Funktionen aufgerufen.

    Die Zeiger zeigen erstmal lediglich auf die Basisklasse. Dann kannst du Funktionen der Basisklasse aufrufen, welche, wenn sie virtuell sind ihrerseits die Funktion der abgeleitenden Klasse aufruft.
    (Ich zweifle nicht daran, dass du das weisst, wollte es nur klar stellen, weil man deinen Satz ziemlich missverstehen kann..;))

    Nachdem du den Zeiger, der auf die Basisklasse zeigt mit dynamic_cast castest, kann er natürlich auch auf die abgeleitete Klasse zeigen. (sofern der cast erfolgreich war).



  • Hm, stimmt... Tut mir leid, danke für die Berichtigung. 🙂

    Aber das Folgende stimmt auch nicht ganz:

    drakon schrieb:

    Dann kannst du Funktionen der Basisklasse aufrufen, welche, wenn sie virtuell sind ihrerseits die Funktion der abgeleitenden Klasse aufruft.

    Es werden nicht zuerst die Funktionen der Basisklasse aufgerufen und anschliessend diejenigen der abgeleiteten. Es wird direkt in der VTable geschaut, welche Funktion die richtige ist...



  • Nexus schrieb:

    Hm, stimmt... Tut mir leid, danke für die Berichtigung. 🙂

    Aber das Folgende stimmt auch nicht ganz:

    drakon schrieb:

    Dann kannst du Funktionen der Basisklasse aufrufen, welche, wenn sie virtuell sind ihrerseits die Funktion der abgeleitenden Klasse aufruft.

    Es werden nicht zuerst die Funktionen der Basisklasse aufgerufen und anschliessend diejenigen der abgeleiteten. Es wird direkt in der VTable geschaut, welche Funktion die richtige ist...

    Ja, klar. War nur ein wenig zur Veranschaulichung. 😉



  • Okay, ich denke, wir sind uns einig. 🙂

    (Hoffentlich haben wir jetzt nicht die anderen Leser des Threads allzu stark verwirrt...)



  • Erstmal danke für die schnelle hilfe.
    Mache es mit den Virtual Funktionen

    vlad_tepesch schrieb:

    virtuellen destruktor in der Basisklasse nicht vergessen, sonst hagelt es memory leaks

    Bin leider in c++ noch ein bischen ein Anfänger.
    heist das ich soll vor den Konstruktor der Basisklasse ein virtual setzten?
    wenn ja, ich bekomme einen fehler wenn ich das mache

    1>LINK : F:\Projekte\MeineC++\INgamesEngineTester\Debug\INGameEngine.dll wurde nicht gefunden oder beim letzten inkrementellen Linkvorgang nicht erstellt; vollständiger Link wird durchgeführt.
    1> Bibliothek "F:\Projekte\MeineC++\INgamesEngineTester\Debug\INGameEngine.lib" und Objekt "F:\Projekte\MeineC++\INgamesEngineTester\Debug\INGameEngine.exp" werden erstellt.
    1>directX.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: virtual __thiscall cZeichnugsElement::~cZeichnugsElement(void)" (??1cZeichnugsElement@@UAE@XZ)" in Funktion ""public: virtual void * __thiscall cZeichnugsElement::`scalar deleting destructor'(unsigned int)" (??_GcZeichnugsElement@@UAEPAXI@Z)".
    1>INGameEngine.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: virtual __thiscall cZeichnugsElement::~cZeichnugsElement(void)" (??1cZeichnugsElement@@UAE@XZ)".
    1>INGameEngine2D.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: virtual __thiscall cZeichnugsElement::~cZeichnugsElement(void)" (??1cZeichnugsElement@@UAE@XZ)".
    1>F:\Projekte\MeineC++\INgamesEngineTester\Debug\INGameEngine.dll : fatal error LNK1120: 1 nicht aufgelöste externe Verweise.

    EDIT: SORRY war mein fehler hatte nichts damit zu tun.



  • Bigmek schrieb:

    Erstmal danke für die schnelle hilfe.
    Mache es mit den Virtual Funktionen

    vlad_tepesch schrieb:

    virtuellen destruktor in der Basisklasse nicht vergessen, sonst hagelt es memory leaks

    Bin leider in c++ noch ein bischen ein Anfänger.
    heist das ich soll vor den Konstruktor der Basisklasse ein virtual setzten?
    wenn ja, ich bekomme einen fehler wenn ich das mache

    Nein, vor den Destruktor

    Bigmek schrieb:

    1>directX.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: virtual __thiscall cZeichnugsElement::~cZeichnugsElement(void)" (??1cZeichnugsElement@@UAE@XZ)" in Funktion ""public: virtual void * __thiscall cZeichnugsElement::`scalar deleting destructor'(unsigned int)" (??_GcZeichnugsElement@@UAEPAXI@Z)".
    1>INGameEngine.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: virtual __thiscall cZeichnugsElement::~cZeichnugsElement(void)" (??1cZeichnugsElement@@UAE@XZ)".
    1>INGameEngine2D.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: virtual __thiscall cZeichnugsElement::~cZeichnugsElement(void)" (??1cZeichnugsElement@@UAE@XZ)".
    

    Du hast aber schon die *.cpp-Datei, in der diese Funktionen definiert sind, dem Projekt hinzugefügt?!
    Bzw die Lib mit reingelinkt, wenn es in ner lib steht...

    bb



  • Funktioniert bereits alles, hatte

    {};
    

    hinter

    virtual ~BASISKLASSE()
    

    vergessen

    PS: DANKE an JustAnotherNoob, drakon, vlad_tepesch, Nexus und unskilled

    Problem gelöst

    EDIT: Passt zwar nicht hierein aber gibt es eine möglichkeit zu überprufen ob mein programm den speicher wider freigiebt den es Reserviert hatt?



  • Passt zwar nicht hierein aber gibt es eine möglichkeit zu überprufen ob mein programm den speicher wider freigiebt den es Reserviert hatt?

    Verschiedene.
    1. Schreib deinen eigenen Memoryleak Detector. ( aufwendig )
    2. Benutz ein externes Programm, das das für dich macht. (ev. teuer)
    3. Benutz API spezifische Funktionen (schnell, unportabel)

    2: http://www.linuxjournal.com/article/6556
    3: http://msdn.microsoft.com/en-us/library/5at7yxcs(VS.71).aspx



  • Nochmals danke.
    wenn jemand jetzt noch jemand erklären kann wie das funktioniert bin ich wunschlos glücklich ansonsten schau ich es mir heute am abend mal an wenn ich mehr zeit habe.

    1 PLUS PLUS für schnelligkeit und hilfsbereitschaft in diesem Forum 👍



  • Bigmek schrieb:

    wenn jemand jetzt noch jemand erklären kann wie das funktioniert bin ich wunschlos glücklich

    Wie was funktioniert? drakon hat ja das Wichtige gesagt...

    Bigmek schrieb:

    1 PLUS PLUS

    Literale kann man nicht inkrementieren... :p



  • Ich meine damit, mein fach englisch ist nicht gut genug um diesen Text zu verstehen.
    Ob mir das jemand erklären kann oder eine linkg auf eine deutsche (vermutlich nicht) hilfe zeigen kann.

    #include <iostream>
    #define PLUS +
    
    using namespace std;
    
    int main()
    {
      int indexer = 0;
      indexer PLUS PLUS;
    
      cout<<indexer<<" für schnelligkeit und hilfsbereitschaft in diesem Forum"<<endl;
    
      //Besser so hehe  :D 
    
      return 0;
    }
    

    hmm get das so oder müsste es so heisen?

    #define PLUS PLUS ++

    oder so

    #define "PLUS PLUS" ++

    hmm verdammt keine ahnung mehr wie das funktioniert

    EDIT: 2 auf 1 geändert.



  • #include <iostream>
    #define PLUS_PLUS ++
    
    #ifdef _DEBUG
    #define _CRTDBG_MAP_ALLOC
    #include <stdlib.h>
    #include <crtdbg.h>
    #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
    #endif
    
    using namespace std;
    
    int main()
    {
    #ifdef _DEBUG
    _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
    #endif
    
      int* indexer = new int ( 1 );
      indexer PLUS_PLUS;
    
      cout<<indexer<<" für schnelligkeit und hilfsbereitschaft in diesem Forum"<<endl;
    
      //Besser so hehe  :D
    
      return 0;
    }
    

    In defines dürfen keine Whitespaces vorkommen.. 😉
    Im übrigen willst du uns eine 2 geben?! 😞

    Naja. Im übrigen kannst du mal die obige Version anschauen. Da hast du die OS-spezifischen Funktionen, die du benutzen kannst. (unter Windows).
    (Schau einfach mal in den Output mit der obigen Version, welche ein Memoryleak auslöst, sowie mal ohne, dann weisst du, wies funktionert. ;))

    Im übrigen kannst du auch ansonsten einmal eines der Programme laden und schauen, ob du draus kommst. 😉 (aber mit Englisch ist es natürlich viel einfacher..)



  • Wenn du mal zuviel Zeit hast und gerade einige Kenntnisse beim Überladen der new / delete -Operatoren und Speicherverwaltung gewinnen willst, kannst du ja deinen eigenen Memory Leak Detector basteln. Das solltest du aber nicht unterschätzen... 😉



  • Vieles vieles dank, funktioniert super, dachte das wäre viel komplizierter,
    muss es dan gleich mal mit meinem Programm testen.
    Hoffe das er nichts findet 😃 .

    PS: hab die 1 in meinem besipiel in eine 0 geändert ist allso jetzt richtig

    1 👍 für schnelligkeit und hilfsbereitschaft in diesem Forum

    EDIIT: JUHU KEINE Speicherleck 🙂


Anmelden zum Antworten