Hallo miteinander. Ich versuche gerade in meinem Projekt (c++) virtuelle Basisklassen und virtuelle Funktionen zu implementieren. Der Aufbau in .h erweist sich für mich als günstig. Die Klasse derived3 leited derived1 u. derived2 ab, wobei base nur einmalig vorhanden ist. Es soll in .cpp dann nur eine Instanz der Klasse derived3 geben. Genau das ist aber mein Problem. Da ich auch virtuelle Funktionen nutzen möchte, die unter best. Umständen entweder func() aus derived1 oder eben func() aus derived2 aufruft, bekomme ich es nicht hin, nur mit einer Instanz d3(Zeiger auf derived3) auszukommen. Sobald ich ja eine Instanz auf derived1 od. 2 erzeuge, ist die Basisklasse ja wieder doppelt drin, was ich ja urspruenglich mit der virtuellen Basisklasse vermeiden wollte??? in .h: ------------------------------------------- class base { virtual void func(); } class derived1: public virtual base { void func(); } class derived2: public virtual base { void func(); } class derived3: public derived1, public derived2 { ... } --------------------------------------------------- //das geht zwar so, ist aber nicht gewuenscht in .cpp: derived3 * d3 = new derived3; derived2 * d2 = d3;//jetzt ist doch die Basisklasse 2 mal erzeugt derived1 * d1 = d3;//und jetzt 3mal test(base * pInst) { pInst->func(); } ... if(flag_d2) ( test(d2); ) if(flag_d1) { test(d1); }
Dein Problem nennt sich Mehrfachvererbung bzw. "multiple inheritance", und hat mit virtuellen Basisklassen und virtuellen Funktionen erst einmal nichts zu tun. In den allermeisten Fällen ist Mehrfachvererbung nicht erforderlich, und Zeichen für ein unglückliches Design. Anfänger sollten es damit halten, wie mit goto: Ja, das gibt es, aber solange man nicht ganz genau weiß, was man tut, Finger weg. Es geht grundsätzlich und fast immer auch besser ohne. Wenn es partout nicht ohne geht, guggst du z.B. hier: http://www.paprots.com/red-inferno/cplusplus/basic/OOP/multi_inheritance/main.htm Oliver
Benny schrieb: > Hallo miteinander. > Ich versuche gerade in meinem Projekt (c++) virtuelle Basisklassen und > virtuelle Funktionen zu implementieren. Virtuelle Vererbung braucht man eigentlich sehr selten. > Sobald ich ja eine Instanz auf derived1 od. 2 erzeuge, ist die > Basisklasse ja wieder doppelt drin, was ich ja urspruenglich mit der > virtuellen Basisklasse vermeiden wollte??? Du erzeugst doch gar keine Instanzen. > //das geht zwar so, ist aber nicht gewuenscht > in .cpp: > derived3 * d3 = new derived3; > derived2 * d2 = d3;//jetzt ist doch die Basisklasse 2 mal erzeugt Nein, warum? Du kopierst einen Zeiger. Mehr nicht. Eine Instanz irgendeiner Klasse wird dabei nicht erzeugt. > derived1 * d1 = d3;//und jetzt 3mal Hier auch nicht. Oliver S. schrieb: > Dein Problem nennt sich Mehrfachvererbung bzw. "multiple inheritance", > und hat mit virtuellen Basisklassen und virtuellen Funktionen erst > einmal nichts zu tun. Das Problem hat auch mit Mehrfachvererbung eigentlich nichts zu tun.
Existieren in der Vererbungshierarchie mehrere Member (daten oder Funktionen) mit gleichen namen, kann man diese aus der Klasse selbst explizit ansprechen. von außen reicht es das member in den entsprechenden Typ zu casten.
1 | derived3::doSomething(){ |
2 | func(); // ruft eigene Implementierung auf |
3 | derived2::func(); // ruft Implementierung aus derived2 auf |
4 | base::func(); // ruft Implementierung von base auf |
5 | }
|
von außen geht das:
1 | if(flag_d2) |
2 | (
|
3 | static_cast<derived2*>(d3)->func(); |
4 | )
|
5 | if(flag_d1) |
6 | {
|
7 | static_cast<derived1*>(d3)->func(); |
8 | }
|
wenn sowas nötig sein sollte, scheint es aber, als wäre dein Design kaputt.
:
Bearbeitet durch User
Vlad Tepesch schrieb: > von außen geht das: > if(flag_d2) > ( > static_cast<derived2*>(d3)->func(); > ) > if(flag_d1) > { > static_cast<derived1*>(d3)->func(); > } Nein, so funktioniert das nicht. So würde es gehen:
1 | if(flag_d2) |
2 | (
|
3 | d3->derived2::func(); |
4 | )
|
5 | if(flag_d1) |
6 | {
|
7 | d3->derived1::func(); |
8 | }
|
Rolf Magnus schrieb: > Das Problem hat auch mit Mehrfachvererbung eigentlich nichts zu tun. Hm, eigentlich doch. Probleme macht das hier: >class derived3: public derived1, public derived2 >{ >... >} wegen der Mehrfachvererbung. Das macht er vermutlich deshalb: Benny schrieb: > Da ich auch virtuelle Funktionen nutzen > möchte, die unter best. Umständen entweder func() aus derived1 oder eben > func() aus derived2 aufruft, Und das wiederum ist schlicht kaputtes Design. Oliver
1 | class base |
2 | {
|
3 | virtual void func(); |
4 | }
|
5 | |
6 | class derived1: public virtual base |
7 | {
|
8 | void func(); |
9 | |
10 | }
|
11 | |
12 | class derived2: public virtual base |
13 | {
|
14 | void func(); |
15 | }
|
Soweit, so gut. Damit geht folgendes:
1 | base *p; |
2 | base *b = new base; |
3 | derived1 *d1 = new derived1; |
4 | derived2 *d1 = new derived2; |
5 | |
6 | p = b; |
7 | p->func(); // ruft base::func auf |
8 | p = d1; |
9 | p->func(); // ruft derived1::func auf |
10 | p = d2; |
11 | p->func(); // ruft derived2::func auf |
Was nicht geht, ist aus einer Instanz von derived1 die Methode derived2::func aufzurufen. Die beiden "kennen" sich gar nicht. Oliver
Oliver S. schrieb: > Rolf Magnus schrieb: >> Das Problem hat auch mit Mehrfachvererbung eigentlich nichts zu tun. > > Hm, eigentlich doch. Probleme macht das hier: >>class derived3: public derived1, public derived2 >>{ >>... >>} > > wegen der Mehrfachvererbung. Das Problem, das er hat, basiert darauf, daß er offenbar Zeiger noch nicht richtig verstanden hat, insbesondere im Zusammenhang mit Vererbung. Er glaubt, daß durch das Kopieren des Zeigers auf das Objekt auf einmal neue Instanzen der Basisklasse entstehen, was aber nicht der Fall ist: Benny schrieb: > derived3 * d3 = new derived3; > derived2 * d2 = d3;//jetzt ist doch die Basisklasse 2 mal erzeugt > derived1 * d1 = d3;//und jetzt 3mal Oliver S. schrieb: > Was nicht geht, ist aus einer Instanz von derived1 die Methode > derived2::func aufzurufen. Die beiden "kennen" sich gar nicht. Mit einem Cast könnte man das schon hinkriegen, aber es wäre natürlich überhaupt nicht sinnvoll, denn dann müßte derived1 ja annehmen, daß es nur als Teil von Klassen verwendet wird, die auch von derived2 abgeleitet sind. Aber dann wäre es nicht mehr sinnvoll, derived1 und derived2 überhaupt zu getrennten Klassen zu machen.
Wie weiter oben schon geschrieben, sollte man als allererstes mal diese ganze Diamond-Hierarchie in Frage stellen. Es wäre höchst ungewöhnlich, dass ein Neuling da drüber stolpert und das unbedingt benötigt.
Rolf Magnus schrieb: > Virtuelle Vererbung braucht man eigentlich sehr selten. Braucht man eigentlich immer.
Bernd K. schrieb: > Rolf Magnus schrieb: > >> Virtuelle Vererbung braucht man eigentlich sehr selten. > > Braucht man eigentlich immer. Ja. Das braucht man eigentlich fast immer. Mehrfachvererbung ist ein bisschen subtil und nicht so oft sinnvoll (auch hier: was willst du eigentlich erreichen?), aber virtuelle Vererbung braucht man ständig.
Sven B. schrieb: > Bernd K. schrieb: >> Rolf Magnus schrieb: >> >>> Virtuelle Vererbung braucht man eigentlich sehr selten. >> >> Braucht man eigentlich immer. > > Ja. Das braucht man eigentlich fast immer. Ich habe es noch nie gebraucht. > Mehrfachvererbung ist ein bisschen subtil und nicht so oft sinnvoll (auch > hier: was willst du eigentlich erreichen?), aber virtuelle Vererbung > braucht man ständig. Die ergibt doch erst bei Mehrfachvererbung einen Sinn.
Rolf Magnus schrieb: > Sven B. schrieb: >> Bernd K. schrieb: >>> Rolf Magnus schrieb: >>> >>>> Virtuelle Vererbung braucht man eigentlich sehr selten. >>> >>> Braucht man eigentlich immer. >> >> Ja. Das braucht man eigentlich fast immer. > > Ich habe es noch nie gebraucht. Ich auch nicht. Gibts ja auch noch nicht so lange. Nur geht es hier auch gar nicht darum. Der TO fängt gerade mal mit virtuellen Funktionen an. Die sind Basis-C++. Oliver
Rolf Magnus schrieb: > Die ergibt doch erst bei Mehrfachvererbung einen Sinn. Ok, ok, "die andere" virtuelle Vererbung :-) Die braucht man tatsächlich kaum.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.