Klassenvererbung..
-
Uff irgendwie glaub ich hab ich das mit der Vererbung noch nicht ganz kapiert..
Ich bekomme folgende Fehlermeldung:[Linker error] undefined reference to `vtable for cStudent'
Ich wette mein Code strotzt nur so von Fehlern, aber ich wär allen die sich antun würden das mal durchzuschauen und paar Erklärungen bzw Änderungsvorschläge hätten verdammt dankbar.
Bin nämlich schon nahe am Verzweifeln..
//an der Stelle wäre wohl ein bisschen heulen angebrachtschneuz.. also:
Ich soll eine abstrakte Klasse Person schreiben die als Attribute den Namen hat und dann abgeleitet Student der zusätzlich das Attribut Matrikelnummer hat.
das ganze soll dann in einem vector<cPerson*> diePersonen gespeichert werden..header datei:
#include <string> using std::string; class cPerson { public: cPerson(); cPerson(string Vorname, string Nachname); virtual ~cPerson(){} virtual string getNachname() const=0; virtual void setNachname(string Nachname)=0; virtual string toString() const=0; protected: string itsNachname; string itsVorname; }; class cStudent : public cPerson { public: cStudent(); cStudent(string Vorname, string Nachname); string toString(); string getNachname() const; virtual void setNachname(string Nachname); virtual string toString() const; string itsMatrikel; }; class cProfessor : public cPerson { public: string toString() const; string itsLehrgebiet; };main.cpp:
#include <iostream> #include <vector> #include "personen.h" //die Headerdatei using namespace std; int main(){ vector<cPerson*> diePersonen; diePersonen.push_back(new cStudent("blabla", "oaschkind")); cout << diePersonen[0] << endl; return 0; } //---------------------------------------------------------------------------- cPerson::cPerson(): itsVorname("Max"), itsNachname("Mustermann"){ cout<<"standardkonstr.\n"; } cPerson::cPerson(string Vorname, string Nachname): itsVorname(Vorname), itsNachname(Nachname){ cout<<"konstr.\n"; } string cPerson::getNachname() const { return itsNachname; } void cPerson::setNachname(string Nachname){ itsNachname=Nachname; } string cPerson::toString() const { return itsVorname+itsNachname; //das ist sicher Blödsinn, habe mir } //darüber noch keine Gedanken gemacht //will das später ausgeben cStudent::cStudent(){ cout<<"studstandarkonstr.\n"; } cStudent::cStudent(string Vorname, string Nachname)//: itsVorname(Vorname), itsNachname(Nachname){ { itsVorname=Vorname; itsNachname=Nachname; cout<<"studkonstr.\n"; } string cStudent::toString() const { } string cProfessor::toString() const { }** wer hier angekommen ist kann sich schon als Helden bezeichen, auch wenn er mir nicht helfen kann

-
Für eine Klasse mit virtuellen Methoden benötigst du eine vtable (dort steht die Zuordnung der Methodennamen zur jeweiligen Implementierung), die der Compiler idR in die selbe Übersetzungeinheit packt wie die erste virtuelle Methode der jeweiligen Klasse. In deinem Fall wäre das die cStudent::getNachname() (die du aber nicht definiert hast).
PS: Es macht übrigens wenig Sinn, eine pur virtuelle Funktion mit einer Definition (Funktionsrumpf) zu versorgen.
-
ich bin selber kein so großer c++-experte, aber mir ist aufgefallen, daß du die funktionen
string cPerson::getNachname() const void cPerson::setNachname(string Nachname) string cPerson::toString() conststatt für cPerson für cStudent schreiben mußt. in der klasse cPerson sind diese funktionen schließlich als =0 deklariert.
return itsVorname+itsNachname;sollte eigentlich funktionieren. nur ein leerzeichen dazwischen wäre halt noch sinnvoll.
EDIT: zu spät...
-
nochwas: anstelle von
cout << diePersonen[0] << endl;muß es
cout << diePersonen[0]->toString() << endl;heißen.
-
besser noch: du entfernst das =0. das macht in deinem falle sowieso keinen sinn. und im programm entfernst du dann
string cStudent::toString() const { } string cProfessor::toString() const { }diese funktionen werden dann einfach von cPerson geerbt. das ist ja schließlich der sinn von OOP

-
Danke erst mal für eure Hilfe!!
Mir ist aber einiges noch nicht ganz klar..CStoll schrieb:
Für eine Klasse mit virtuellen Methoden benötigst du eine vtable (dort steht die Zuordnung der Methodennamen zur jeweiligen Implementierung), die der Compiler idR in die selbe Übersetzungeinheit packt wie die erste virtuelle Methode der jeweiligen Klasse. In deinem Fall wäre das die cStudent::getNachname() (die du aber nicht definiert hast).
hmm ich dachte dass cStudent das getNachname erbt und ich nicht definieren muss(dachte das is der Sinn dieser Vererbung).
Ist wohl nicht so weils virtuell ist und ich muss es auch in cStudent schreiben oder?? DH ich definiere diese Funktion in der Basisklasse (virtuell) nur damit die Ableitungen auf die Attribute der Basisklasse zugreifen dürfen..
Ich hoffe ich hab das jetzt richtig verstanden..PS: Es macht übrigens wenig Sinn, eine pur virtuelle Funktion mit einer Definition (Funktionsrumpf) zu versorgen.
Ich soll aber eine Standardimplementierung (zumindest für toString) in der Basisklasse schreiben, die den Namen ausgibt
@Konfusius
Ich muss die Klasse cPerson rein abstrakt halten deswegen hab ich alle Funktionen darin rein virtuell gemacht. Auch wenns vielleicht keinen Sinn macht, so ist die Angabe...
Außerdem kommt instring cStudent::toString() const { ...... }noch etwas hinein. Soll nämlich dann alle Attribute ausgeben
-
PuppyOnAcid schrieb:
hmm ich dachte dass cStudent das getNachname erbt und ich nicht definieren muss(dachte das is der Sinn dieser Vererbung).
cStudent erbt getNachname, richtig. Da Du getNachname aber selbst nochmal definiert, "überschreibst" Du die geerbte Methode mit einer eigenen.
Ich soll aber eine Standardimplementierung (zumindest für toString) in der Basisklasse schreiben, die den Namen ausgibt
Entweder implementierung oder =0 (abstrakt), entscheide Dich

Eine abstrakte Implementierung gibbet nichIch muss die Klasse cPerson rein abstrakt halten deswegen hab ich alle Funktionen darin rein virtuell gemacht. Auch wenns vielleicht keinen Sinn macht, so ist die Angabe...
Widerspricht der Angabe "soll Standardimplementierung enthalten"
Eine rein abstrakte Klasse hat keine Impl, deshalb heisst sie rein abstrakt.
-
LordJaxom schrieb:
cStudent erbt getNachname, richtig. Da Du getNachname aber selbst nochmal definiert, "überschreibst" Du die geerbte Methode mit einer eigenen.
Heißt das wenn ich getNachname in cStudent nicht überschreibe sondern weglasse dann würde es auch funktionieren auch wenn sie in der Basisklasse rein virtuell ist?
LordJaxom schrieb:
Entweder implementierung oder =0 (abstrakt), entscheide Dich

Eine abstrakte Implementierung gibbet nichIch muss die Klasse cPerson rein abstrakt halten deswegen hab ich alle Funktionen darin rein virtuell gemacht. Auch wenns vielleicht keinen Sinn macht, so ist die Angabe...
Widerspricht der Angabe "soll Standardimplementierung enthalten"
Eine rein abstrakte Klasse hat keine Impl, deshalb heisst sie rein abstrakt.Na toll..
Dann überlegt sich mein Prof. die Angaben so gut wie seine Vorlesung..
Selbst ein Kollege von mir der eigentlich erfahrener c++ Programmierer ist hat gesagt er wird aus den Gedankengängen manchmal nicht schlau, geschweige denn würde irgend etwas verstehen wenn ers nicht schon wüsste..
und das Script ist genauso scheiße..
Deswegen muss ich euch so zuspammen, weil alles kann ich mir leider nicht durch Tutorials aneignen
-
PuppyOnAcid schrieb:
LordJaxom schrieb:
cStudent erbt getNachname, richtig. Da Du getNachname aber selbst nochmal definiert, "überschreibst" Du die geerbte Methode mit einer eigenen.
Heißt das wenn ich getNachname in cStudent nicht überschreibe sondern weglasse dann würde es auch funktionieren auch wenn sie in der Basisklasse rein virtuell ist?
Wenn cPerson::getNachname() pur virtuell ist, wird sich der Compiler beschweren, daß du sie nicht verwenden kannst (unabhängig davon, ob dort eine Implementierung steht) - du benötigst trotzdem noch eine cStudent::getNachname(), die notfalls die Default-Implementation direkt aufrufen kann.
(PS: Die einzige sinnvolle Anwendung von pur virtuell UND definiert sind afaik Destruktoren)
-
CStoll schrieb:
(PS: Die einzige sinnvolle Anwendung von pur virtuell UND definiert sind afaik Destruktoren)
"einzig sinnvoll" halte ich hier für die falsche Bezeichnung. Immerhin müssen pur virtuelle Desktruktoren auch implementiert sein.
Ich finde Implementationen von pur virtuellen Funktion als default-Implemntation durchaus sinnvoll.
-
Danke Leute, habt mir sehr geholfen!
Es funktioniert wie es soll, welch oh Wunder
Konnte mir das restlich Nötige aus euren comments und den Tutorials zusammenreimen...thx
-
also, ich hab meine c++-kenntnisse aus dem "Breymann". soll angeblich das c++-standardwerk in deutschland sein. dieses buch ist der letzte müll und deshalb habe ich auch immer noch so ziemlich null ahnung von c++ obwohl ich es vollständig gelesen und auch verstanden habe. wenn diese buch den stand der informatikausbildung in deutschland darstellt, dann gute nacht...