/* feedback bij reeks 11 * PROBLEEM : bestandssysteem * INHOUD FEEDBACK : const qualifiers * undefined reference to memberfunction of base class * vtable-fout */ /* * Hier wordt een poging gedaan om zoekstrategieen aan te dragen. * Zodat ook andere fouten zelfstandig opgespoord kunnen worden. * */ OPM 1 Foutmelding: passing `const Node' as `this' argument of `void Node::setParent(const Map*)' discards qualifiers Hoe vind je de fout? Uit de foutmelding valt af te leiden dat je het 'huidige object' (dus de Node waarop je setParent oproept) als const beschouwt, maar dat setParent dat niet zal respecteren. Zoek daarom naar de specificaties van setParent. Dit blijkt geen const-memberfunctie te zijn, dus kan die (in principe) wijzigingen aanbrengen aan het huidige object. OPM 2 Code: void Map::addChild(const Node* iChild) { mChildren.push_back(iChild); const Map* tParent = this; iChild->setParent(tParent); } Bijhorende foutmelding: undefined reference to `Node::setParent(Map const*) const' Hoe vind je de fout? Blijkbaar kan de lidfunctie van de afgeleide klasse Map niet aan de protected lidfunctie van de hoofdklasse Node. Nochtans zou dit wel mogelijk moeten zijn (daar dient het codewoord 'protected' toch voor?) Probeer uit wat er gebeurt als je setParent even publiek zet. Dan is de fout blijkbaar weg. Probeer uit wat er gebeurt als je setParent protected laat, maar setParent oproept op het huidige object van addChild. Dat lukt ook: de fout verdwijnt. Dus: blijkbaar zorgt het codewoord 'protected' ervoor dat je wel aan de lidfuncties/dataleden van de hoofdklasse kan, maar alleen indien toegepast op het huidige object van de oproepende lidfunctie van de afgeleide klasse. Gaat het om een parameter van de hoofdklasse waarop je een protected lidfunctie wil toepassen, dan loopt het mis. Merk op: in Java kan dit wel. Oplossing: friend (dan toch... maar wees er zuinig op!) OPM 3 Code: class Map; // Forward Declaration // Als we FD gebruiken MOETEN we pointers gebruiken van die klasse class Knoop { public: virtual void print(); Knoop(const std::string &); ~Knoop(){} protected: std::string naam; Map *ouder; }; class Map : public Knoop { public: Map(const std::string &_naam) : Knoop(_naam) { kinderen.reserve(50); } void print(){ std::cout << "Map " << naam << std::endl; [...] } protected: std::vector kinderen; }; class Bestand : public Knoop { public: Bestand(const std::string &_naam) : Knoop(_naam){} void print(){ std::cout << "Bestand " << naam << std::endl; } protected: std::string inhoud; }; Bijhorende foutmelding: build/Debug/GNU-Linux-x86/main.o: In function `~Knoop': [...]/bestandsys.h:33: undefined reference to `vtable for Knoop' [...]/bestandsys.h:33: undefined reference to `vtable for Knoop' build/Debug/GNU-Linux-x86/main.o: In function `Knoop': [...]/bestandsys.h:30: undefined reference to `vtable for Knoop' [...]/bestandsys.h:30: undefined reference to `vtable for Knoop' build/Debug/GNU-Linux-x86/main.o:(.rodata._ZTI3Map[typeinfo for Map]+0x8): undefined reference to `typeinfo for Knoop' build/Debug/GNU-Linux-x86/main.o:(.rodata._ZTI7Bestand[typeinfo for Bestand]+0x8): undefined reference to `typeinfo for Knoop' Oplossing: vtable-problemen hebben te maken met virtuele functies. Het volstaat om de virtuele functie in de basisklasse expliciet geen implementatie te geven, door er "=0" achter te hangen. Zie http://www.cplusplus.com/doc/tutorial/polymorphism/