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.
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:
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
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 3malOliver 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.
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.