Vraag & Antwoord

Programmeren

[c++] inheritance vraag.

8 antwoorden
  • Ik ben een beetje aan het beginnen met c++. Ik kwam er per ongeluk achter dat het volgende niet werkt: Je hebt een hoofdklasse en een aantal subklassen. De hoofdklasse wordt in principe nooit geinstancieerd. De subklassen erven van de hoofdklasse een vector<hoofdklasse>, dus kan weer andere (subklassen van) hoofdklasse bevatten. Een boom-model dus. De hoofdklasse heeft een virtuele functie die door elke subklasse weer anders wordt 'overridden': [code:1:d6ce8cd13c] #include <iostream> #include <string> #include <vector> using namespace std; class TFiguur { public: vector<TFiguur> childs; virtual void watBenIk() {}; }; class TVierkant: public TFiguur { public: virtual void watBenIk() { cout << "Vierkant" << endl; for (unsigned i=0; i<childs.size(); i++) childs[i]->watBenIk(); // hier wordt de (lege) TFiguur:watBenIk() uitgevoerd... }; }; class TDriehoek: public TFiguur { public: virtual void watBenIk() { cout << "Driehoek" << endl; for (unsigned i=0; i<childs.size(); i++) childs[i].watBenIk(); // hier wordt de (lege) TFiguur:watBenIk() uitgevoerd... }; }; int main() { TVierkant Topnode; Topnode.childs.push_back(TVierkant()); Topnode.childs.push_back(TDriehoek()); Topnode.watBenIk(); return 0; } [/code:1:d6ce8cd13c] het is alleen zo dat bij childs[i].watBenIk() vanuit void watBenIk() niet TVierkant::watBenIk() of TDriehoek::watBenIk() wordt aangeroepen, maar de -lege- TFiguur::watBenIk(). Ik kan het oplossen door niet een vector<TFiguur> te maken maar een vector met pointers naar TFiguur: vector<TFiguur *>, en nieuwe childs toe te voegen met Topnode.childs.push_back([b:d6ce8cd13c]new[/b:d6ce8cd13c] TVierkant()/TDriehoek());. Ik vraag mij af waarom dit zo is. Kan iemand mij dit uitleggen ?[/b]
  • (Dit hoort bij programmeren) Mijn C++ zit eerlijk gezegd ver, maar ik denk dat je constructors mist in je klassen.
  • Omdat er geen parameters meegegeven hoeven worden aan de klassen bij het creeren, heb ik de constructors weggelaten. De compiler maakt dan zelf een defaultconstructor: TFiguur(), TVierkant() en TDriehoek(). Ik had ze idd ook zelf kunnen declareren: TFiguur() {} TVierkant():TFiguur() {} en TDriehoek():TFiguur() {} maar de werking verandert dan niet, en daar wordt het voor het topic ook niet overzichtelijker door denk ik.
  • Default constructors ok. Maar ik denk ook dat je de basisklasse constructor in je afgeleide klasse moet aanroepen om een afgeleide klasse te kunnen krijgen.
  • Helaas, als ik de constructors aanmaak: [code] class TFiguur { ... TFiguur() {}; ... } class TVierkant { ... TVierkant():TFiguur() {}; ... } is het resultaat hetzelfde. En hij deed het immers wel als ik slechts de member vector<TFiguur> wijzigde in vector<TFiguur* > ! Daarom snap ik het ook niet echt.
  • Niks geen extra constructors/destructors toevoegen (is alleen nodig om straks 'childs' goed te initialiseren). Het voorbeeld dat je gebruikt is gewoon onnodig complex om de fout te vinden. Daarnaast is er een belangrijke fout in de afgeleidde klassen. [code:1:06b8753c3f]virtual[/code:1:06b8753c3f] moet [code:1:06b8753c3f]overload[/code:1:06b8753c3f] zijn. Zoals jij ze nu hebt gedefinieerd zal de compiler je waarschijnlijk warnings geven in de trend van "watBenIk(); is already defined ..." Dit voorbeeld is simpeler en werkt beter : [code:1:06b8753c3f] void main() { TFiguur mijnDemo; mijnDemo = new TVierkant(); mijnDemo.watBenIk(); // resultaat : een vierkant ... } [/code:1:06b8753c3f] Stap eerst eens af van dat die interne variabele 'childs' van het vektor-type want dat verwart alleen maar het voorbeeld. De enige manier om in jouw voorbeeld die driehoek/vierkant terug te krijgen is om ze via childs-property op te halen. Topnode is in jouw voorbeeld namelijk gewoon een instantie van het type TFiguur. Het is dus voor mij redelijk logisch dat [code:1:06b8753c3f]Topnode.watBenIk();[/code:1:06b8753c3f] niks oplevert.
  • Je moet een vector maken van TFiguur pointers, want als je het in deze opstelling doet (op de stack), dan kun je geen gebruik maken van de zogenaamde polymorfe eigenschappen van je object. 8) Zoiets dus: [code:1:38c9a5fbf7]#include <iostream> #include <string> #include <vector> using namespace std; class TFiguur { public: vector<TFiguur*> childs; //< Pointer hier virtual void watBenIk() {}; }; class TVierkant: public TFiguur { public: virtual void watBenIk() { cout << "Vierkant" << endl; for (unsigned i=0; i<childs.size(); i++) childs[i]->watBenIk(); }; }; class TDriehoek: public TFiguur { public: virtual void watBenIk() { cout << "Driehoek" << endl; for (unsigned i=0; i<childs.size(); i++) childs[i]->watBenIk(); }; }; int main() { TVierkant Topnode; Topnode.childs.push_back(new TVierkant()); //< New operator Topnode.childs.push_back(new TDriehoek()); Topnode.watBenIk(); return 0; }[/code:1:38c9a5fbf7] Vergeet wel niet dat je alle objecten die je met een new-operator aanmaakt, ook weer moet opruimen met delete he. Want deze code lekt geheugen. Daar kun je een virtual destructor in TFiguur voor gebruiken. Enne, JaFO... van dat overload-keyword had ik nog nooit gehoord. Ik heb even gegoogled, en ben tot de conclusie gekomen dat het een overbodig sleutelwoord is en door nieuwe compilers niet eens meer ondersteund wordt. Dus ik denk niet dat dat een goede oplossing is. Tenzij musicom76 ook met zo'n oude compiler werkt. ;)
  • tja ... ben dan ook geen expert op C++ gebied ;) C# kent het weer wel dacht ik ... gezien de aard van het probleem leek het of dat de oorzaak van de fout was. En zelf destructors aanroepen ? Dat is ook zoiets ouderwets ... :p 'moderne' compilers zijn namelijk zo slim om zelf van instanties de destructor weg te gooien. Enige nadeel is dat je dan geen controle hebt over het moment van destructie. De .Net-talen doen dat in ieder geval zo. Waarom zou je geen gebruik kunnen maken van polymorphy als het 'maar' pointers zijn ? Je typecast het ding naar 'pointer' om het op de stack te kieperen en als je het er af haalt dan typecast je die 'pointer' naar de basisklasse (TFiguur in dit geval).

Beantwoord deze vraag

Weet jij het antwoord op deze vraag? Registreer of meld je aan met je account

Dit is een gearchiveerde pagina. Antwoorden is niet meer mogelijk.