Vererbung und Inline
-
Hallo,
ich habe folgende Klassen programmiert:#ifndef _PERSON_H #define _PERSON_H #include <string> class Person { public: Person(const std::string NN, const std::string VN):Nachname(NN),Vorname(VN){} virtual ~Person() {} const std::string& getNachname() const {return Nachname;} const std::string& getVorname() const {return Vorname;} inline virtual std::string toString() const=0; private: std::string Nachname; std::string Vorname; }; #endifPerson.cpp
#include "Person.h" #include <string> using namespace std; std::string Person::toString() const { return (Nachname + "," + Vorname); }#ifndef _STUDENTIN_H #define _STUDENTIN_H #include "Person.h" #include <string> class StudentIn: public Person { public: StudentIn(const std::string NN, const std::string VN, const std::string Mat) :Person(NN,VN), Matrikelnummer(Mat) {} virtual ~StudentIn(){} virtual std::string toString() const { return Person::toString(); } private: std::string Matrikelnummer; }; #endifUnd zwar bekomme ich zum einen einen Linker Error:
Undefined symbols: "Person::toString() const", referenced from: StudentIn::toString() constin main.o ld: symbol(s) not found collect2: ld returned 1 exit statusUnd dann würde mich noch interessieren, warum ich bei der Virtuellen Methode toStr() den Rückgabewert per Kopie machen muss und es nicht per Referenz geht.
-
inline virtual ... =0. Was?
Lass das inline weg! Das hat da nichts zu suchen und macht auch keinen Sinn. inline kommt bei der Definition hin. Dann hast du auch keinen linker-error mehr.toStr() erzeugt einen temporören String. Dieser wird zerstört, sobald die Methode abgearbeitet ist. Und ein solches Objkt kann man nicht derferenzieren - existiert ja nimmer! Sollte es funktionier ist das Zufall - undefiniertes Verhalten.
Deshalb muss eine Kopie zurückgegeben werden.
-
Noob12345 schrieb:
#ifndef _PERSON_H #define _PERSON_HStopp. Du sollst doch nicht eigene Bezeichner benutzen, die mit _ anfangen. Schon gar nicht, wenn danach ein Großbuchstabe folgt. Doppel-Unterstriche sind auch verboten. Diese Bezeichner sind reserviert.
inline virtual std::string toString() const=0;Prinzipiell müssen inline-Funktionen immer in jeder Übersetzungseinheit definiert werden, wo sie benutzt werden. Du hast die Defition ja nur in einem cpp-File und rufst sie von einem anderen aus auf. Das ist nicht erlaubt.
[quote="Noob12345"]
Und zwar bekomme ich zum einen einen Linker Error:Undefined symbols: "Person::toString() const", referenced from: StudentIn::toString() constin main.o ld: symbol(s) not found collect2: ld returned 1 exit statusVerwundert nicht. Du hast Dich nicht an die inline-Regeln gehalten.
Noob12345 schrieb:
Und dann würde mich noch interessieren, warum ich bei der Virtuellen Methode toStr() den Rückgabewert per Kopie machen muss und es nicht per Referenz geht.
Referenz worauf denn? Wenn das, was referenziert wird, lange genug "lebt", kannst Du auch eine Referenz zurückgeben. Das Ergebnis von Vorname+","+Nachname ist ein temporäres, im automatischen Speicher lebendes Objekt, Du nicht an eine Referenz binden kannst. Ein Umweg über eine lokale Variable sollte zumindest eine Compiler-Warnung geben; denn Du würdest eine Referenz auf ein lokales Objekt zurückgeben, was nach Ende der Funktion nicht mehr da ist.
-
Also das _... macht meine IDE automatisch, wenn ich eine neue Klasse anlege (NetBeans).
Wie müsste ich das denn inline schreiben, wenn ich es in der cpp definieren will? In der .h das inline weglassen und in der cpp da zuschreiben geht auch nicht.
-
Noob12345 schrieb:
Also das _... macht meine IDE automatisch, wenn ich eine neue Klasse anlege (NetBeans).
Wie müsste ich das denn inline schreiben, wenn ich es in der cpp definieren will? In der .h das inline weglassen und in der cpp da zuschreiben geht auch nicht.
Eine virtuelle Funktion kann nicht inline sein, da erst zur Laufzeit entschieden wird, welcher code ausgeführt wird. Macht null Sinn.
Wenn du eine inline Funktion verwenden möchtest, solltest du die Implementierung im Header haben, nicht im .cpp, denn der Compiler muss die Implementierung kennen um inlinen zu können.
-
Stefan schrieb:
Eine virtuelle Funktion kann nicht inline sein, da erst zur Laufzeit entschieden wird, welcher code ausgeführt wird. Macht null Sinn.
Jein. Die Aussage ist vollkommen korrekt, wenn es sich um polymorphen Zugriff handelt. Da hat der Compiler keine Chance zu inlinen.
Aber zum Glück ist der Compiler nicht doof und erkennt wenn eben kein Polymorpher ZTugriff stattfindet. Z.B. wenn das Objekt im automatischen Speicher liegt. Dann wird sehr wohl geinlined. Also kann ein inline auch bei einer virtuellen Methode Sinn machen.
-
Also geht das inline in diesem Fall nur in der Header Datei? Also in der cpp ist es unmöglich?
-
Noob12345 schrieb:
Also geht das inline in diesem Fall nur in der Header Datei? Also in der cpp ist es unmöglich?
Nicht nur in diesem Fall geht es nicht. Es ist in jedem Fall unmöglich eine Methodendefinition in einer .cpp zu inlinen.
-
l'abra d'or schrieb:
Nicht nur in diesem Fall geht es nicht. Es ist in jedem Fall unmöglich eine Methodendefinition in einer .cpp zu inlinen.
Stimmt so auch nicht (mehr) ganz. Das Inlining zur Compilezeit ist nicht möglich, wenn der Header in einer anderen ÜE eingebunden wird. Soweit richtig. In derselben ÜE ist es natürlich möglich, und es gibt auch Techniken, die das Inlining während des Linkens und IIRC zum Teil auch noch später ermöglichen.
So oder so ist es aber meistens sinnfrei, inline explizit anzugeben, weil der Compiler selber bestimmt, ob er inlinen kann und möchte.
-
Ah danke. Wenn mir jetzt noch jemand erklären kann, warum NetBeans falsch definded @default....
-
pumuckl schrieb:
Das Inlining zur Compilezeit ist nicht möglich, wenn der Header in einer anderen ÜE eingebunden wird.
Zum Glück gibt es deshalb ja auch inlining zur Linkzeit

@OP:
inline heisst nicht "diese Funktion inlinen". inline heisst vereinfacht nur "lass mich diese Funktion in einer Header Datei definieren". In deinem Fall ist es komplett unnötig.
-
Shade Of Mine schrieb:
pumuckl schrieb:
Das Inlining zur Compilezeit ist nicht möglich, wenn der Header in einer anderen ÜE eingebunden wird.
Zum Glück gibt es deshalb ja auch inlining zur Linkzeit

Genau das habe ich doch geschrieben

-
pumuckl schrieb:
Genau das habe ich doch geschrieben

ja hast du, mein Fehler :o