Problem mit Basisklassenzeiger
-
Hier die Klassen:
class Basis { public: virtual void Funktion(void) = 0; }; class Abgeleitet:public Basis { public: void Funktion(void){/*...*/}; void Funktion2(void){/*...*/}; };Ich hab folgendes Problem:
Abgeleitet Abg; Basis* pBasis = new Abgeleitet; pBasis = &Abg;pBasis->Funktion() aufzurufen ist kein Problem,aber ich will auch pBasis->Funktion2 aufrufen können. Dabei krieg ich aber immer eine Fehlermeldung.
Ist das überhaupt möglich pBasis->Funktion2() aufzurufen und wenn ja wie?Danke
-
Funktion2 ist doch in Basis gar nicht definiert
Wie soll das ganze dann aufgerufen werden?
Du kannst lediglich von einer Instanz der Klasse Abgeleitet auf Funktion2 zugreifen.
andererseits könntest du noch in Basis Funktion2 auch pure virtual definieren. Diese müsste allerdings dann wiederum in jeder abgeleiteten Klasse implementiert werden.
Oder du deklarierst Funktion2 in Basis mit einem leeren Rumpf (und auch virtuell).
Dann kannste dir aussuchen, ob du sie implementieren möchtest, oder nicht
-
(1) Speicherloch (memleak), da du eine 'Abgeleitete'-Klasseninstanz auf dem Heap und auf dem Stack erstellst. Die auf dem Heap wird nicht automatisch gelöscht und du verlierst deinen Zeiger auf den Bereich, da du pBasis umlenkst.
(2) Casten.struct foo { virtual void func_first() { std::clog << "foo::func() called" << std::endl; }; struct bar : public foo { void func_first() { std::clog << "bar::func() called" << std::endl; void func_second() { std::clog << "bar::func() called" << std::endl; }; int main() { foo* ptr_instance(new bar); foo->func_first(); static_cast<bar*>(ptr_instance)->func_second(); }...
}
-
(D)Evil schrieb:
(2) Casten.
Aber bitte richtig. Für einen Downcast in der Hierachie sollte man dynamic_cast verwenden.
cu André
-
solange foo keine virtuelle basis von bar ist und der zeiger tatsächlich auf bar zeigt, ist ein
static_castdurchaus erlaubt.aber da ich glaube, dass du das wohl weißt: solange man sich sicher ist, dass die bedingungen zutreffen, spricht imo nichts gegen den
static_cast, wobei man sich dann natürlich die frage stellen sollte, warum überhaupt mit einem zeiger auf die basis arbeiten?
-
(D)Evil schrieb:
...
... static_cast<bar*>(ptr_instance)->func_second(); }...
}Naja, das funktioniert ja auch komplett ohne "func_first":
struct foo { virtual ~foo() {} }; struct bar : public foo { void func_second() { std::clog << "bar::func() called" << std::endl; }; int main() { foo* ptr_instance(new bar); static_cast<bar*>(ptr_instance)->func_second(); }
Ich denke, die (saubere) Antwort auf die eigentliche Frage
Programmierer schrieb:
...
Ist das überhaupt möglich pBasis->Funktion2() aufzurufen und wenn ja wie?...hat Vorden eigentlich schon gegeben: Ohne virtual besser gar nicht !

Gruß,
Simon2.
-
queer_boy schrieb:
solange foo keine virtuelle basis von bar ist und der zeiger tatsächlich auf bar zeigt, ist ein
static_castdurchaus erlaubt.aber da ich glaube, dass du das wohl weißt: solange man sich sicher ist, dass die bedingungen zutreffen, spricht imo nichts gegen den
static_cast, wobei man sich dann natürlich die frage stellen sollte, warum überhaupt mit einem zeiger auf die basis arbeiten?Aber wehe es kommen mehrere konkrete Klassen an dieser Stelle ins Spiel.
Sorry, ich ziehe in dem Fall Sicherheit der Performance vor (Und sofern auch nur die Chance existiert das der Zeiger nicht auf die bei static_cast angegebene Klasse verweist, ist ein dynamic_cast definitiv der richtige Weg).
Da hier durchaus auch Anfänger mitlesen, möchte ich schlicht und ergreifend vermeiden das diese mit unnötigen und schwer auffindbaren Fehlern konfrontiert werden!Performance mag eine gut gemeinte Option sein, aber am Anfang sollte immer die Sicherheit gelten.
cu André
-
dynamic_cast ist nicht die "sichere" Variante von static_cast - da liegt ein Verständnisfehler vor. Es gibt Fälle, in denen nur dynamic_cast fehlschlägt, nicht aber static_cast (man denke an nicht-virtuelle Mehrfachvererbung, bei nicht-polymorphe Klassen sowieso), und umgekehrt ebenso. Grundsätzlich haben beide Casts unterschiedliche Aufgaben, einer bedient sich statischer, der andere benutzt dynamische Typinformationen. Die Auswahl des richtigen Casts hängt folglich nicht von irgendwelchen schwer fassbaren Sicherheitskriterien ab, sondern schlicht und ergreifend von den Nebenbedingungen, die an das Argument gestellt werden können.