c++, Verberung, warum krieg ich hier einen linker Fehler?
-
volkard schrieb:
Ich habe es gerade durch den GCC laufen lassen und der macht keinen Linkerfehler.
Hm... mist hab hier nen Visual Studio 2003

Muss ich da eine bestimmte Projekteinstellung haben?
-
Man ruft auch keine virtuellen Methoden im Konstruktor auf!!! Grundregel, absolut niemals nicht!!!
Sry für die vielen Ausrufezeichen...
Google sollte da ausreichend Erklärungen liefern.
-
Im Konstruktor von CBaseClass wird CBaseClass::GetStr() aufgerufen (nicht etwa, wie Du vielleicht annimmst, CSubClass::GetStr()), für die es keine Implementierung gibt. Grund ist, dass das CSubClass-Objekt zu dem Zeitpunkt noch nicht vollständig initialisiert ist.
Methoden können übrigens rein virtuell sein und dennoch eine Implementierung besitzen.
@volkard:
Die Compiler verhalten sich unterschiedlich: Während MSVC nach der nicht vorhandenen Implementierung sucht, erstellt GCC eine Dummy-Implementierung, die das Programm mit der Meldung "pure virtual function called" abbricht.
-
gcc-4.4.3 (eigentlich ja ld aus binutils-2.20.1) bricht bei folgendem Programm
struct Base { Base() { fun(); } virtual void fun() =0; }; struct Der : public Base { void fun() { } }; int main() { Der d; Base *b = new Der; }mit diesem Fehler ab
virt_fun_in_constr.cpp: In constructor »Base::Base()«: virt_fun_in_constr.cpp:4: Warnung: abstract virtual »virtual void Base::fun()« called from constructor /tmp/ccAz8GqY.o: In function `Base::Base()': virt_fun_in_constr.cpp:(.text._ZN4BaseC2Ev[Base::Base()]+0x1f): undefined reference to `Base::fun()' collect2: ld gab 1 als Ende-Status zurück
-
LordJaxom schrieb:
@volkard:
Die Compiler verhalten sich unterschiedlich: Während MSVC nach der nicht vorhandenen Implementierung sucht, erstellt GCC eine Dummy-Implementierung, die das Programm mit der Meldung "pure virtual function called" abbricht.Nichtmal das.
Er sagt auch "undefined reference to CBaseClass::GetStr()". Ich habe vergessen, in der main so ein Objekt anzulegen.Aber mit meinen Debug-Einstellungen kommt was recht feines.
D:\...\main.cpp||In constructor 'CBaseClass::CBaseClass()':| D:\...\main.cpp|11|warning: abstract virtual 'virtual std::string CBaseClass::GetStr()' called from constructor|
-
LordJaxom schrieb:
Im Konstruktor von CBaseClass wird CBaseClass::GetStr() aufgerufen (nicht etwa, wie Du vielleicht annimmst, CSubClass::GetStr()), für die es keine Implementierung gibt. Grund ist, dass das CSubClass-Objekt zu dem Zeitpunkt noch nicht vollständig initialisiert ist.
Methoden können übrigens rein virtuell sein und dennoch eine Implementierung besitzen.
@volkard:
Die Compiler verhalten sich unterschiedlich: Während MSVC nach der nicht vorhandenen Implementierung sucht, erstellt GCC eine Dummy-Implementierung, die das Programm mit der Meldung "pure virtual function called" abbricht.Ok danke für die Erklärungen.

Ich find das n bissi doof, aber wenn das c++ so macht is es ok
Ich komm von C# und da geht so etwas:
public abstract class BaseClass { public BaseClass () { GetStr (); } public abstract String GetStr (); } public class SubClass : BaseClass { public override String GetStr () { return ""; } }Der ruft dann tatsächlich die GetStr () von SubClass auf.
Hatte Gedacht, da sich die Sprachen ähneln kann c++ so etwas auch.
Der Grund weswegen ich frag, die Basisklasse hat Member für Parameter die jede Abgeleitete Klasse selber festlegt. Damit die nicht vergessen werden zu initialiseren dacht ich, ich ruf die Methode im Kontruktor auf.
Ich müsste es also so machen??
class CBaseClass { public : int m_Parameter1; int m_Parameter2; int m_Parameter3; CBaseClass () { //Init (); // Geht nicht } virtual void Init () = 0; }; class CSubClass : public CBaseClass { public : void Init () { m_Parameter1 = 1; m_Parameter2 = 2; m_Parameter3 = 3; } }; CSubClass SubClass; SubClass.Init ();Wenn jemand vergisst die Init aufzurfen dann klapperts

-
In dem Fall macht man Konstruktor private und bietet eine statische factory-Methode an, die dann gefahrlos ein Objekt erstellen und danach die init()-Methode aufrufen kann.
-
Dafür sind doch Konstruktoren und Initialisierungslisten da...
class base { protected: int m_Parameter1; int m_Parameter2; int m_Parameter3; explicit base(int p1=0, int p2=0, int p3=0) : m_Parameter1(p1) , m_Parameter2(p2) , m_Parameter3(p3) {} public : virtual std::string getstr() const = 0; }; class derived : public base { public : derived() : base(1,2,3) {} std::string getstr() const; // muss noch definiert werden }; : derived d;Achte auch darauf, dass die Definitionen von "Funktionen" innerhalb von Klassen inline impliziert.
-
Die Initialisierungslisten kenn ich schon, ist aber für meinen Fall nicht so gut.
Eine Factory-Methode das klingt super
Vielen Dank an alle die geholfen haben

-
Sieben schrieb:
Die Initialisierungslisten kenn ich schon, ist aber für meinen Fall nicht so gut.
Warum nicht? Du solltest sie Zuweisungen im Konstruktorrumpf oder gar in manuell aufzurufenden
Init()-Funktionen vorziehen.