Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

the[V]oid

Alter Hase

  • »the[V]oid« ist der Autor dieses Themas

Beiträge: 775

Wohnort: Aachen

  • Private Nachricht senden

1

13.01.2010, 10:10

Problem mit Vererbung (Diamond Problem)

Hallo

Als Beispiel folgender Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#define LESS_PARAMS // einige wenige Parameter

#define MANY_PARAMS // ein Haufen Parameter


class Base
{
public:
  A( MANY_PARAMS );
};

class Sub1 : virtual public Base
{
public:
  Sub1( LESS_PARAMS );
};

class Sub2 : virtual public Base
{
public:
  Sub2( LESS_PARAMS );
};

class D : public Sub1, public Sub2
{
public:
  D( LESS_PARAMS )
    : Sub1( /* delegiere alle Parameter */ ),
      Sub2( /* delegiere alle Parameter */ )
};


Nun erhalte ich bei der Implementierung des Konstruktors von D die Fehlermeldung, dass Base keinen Standardkonstruktor hätte.
Dies ist auch der Fall, auch tue ich diesen Fehler irgendwie halb nachvollziehen.
Aber dennoch bin ich mir recht sicher, dass meine Klasse D im OOP-Sinne sowohl Sub1, als auch Sub2 ist.
Gibt es eine Möglichkeit, das ganze so zu implementieren, dass der Compiler es akzeptiert?

Danke im Voraus
<< an dieser Stelle ist eine Signatur verstorben >>

xardias

Community-Fossil

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

2

13.01.2010, 10:48

Wenn ich mich nicht irre musst du in der Klasse D ebenfalls den Konstruktorauf an Base delegieren. Ich bin grad nicht mehr ganz in dem Thema aber ich denke der Grund ist der Folgende:

Durch die virtuelle Vererbung sorgst du ja quasi dafür, dass es keine doppeldeutigkeiten bezüglich der gemeinsamen Basisklasse gibt. Daher kannst du den Konstruktoraufruf von Base nicht an Sub1 oder Sub2 auslagern. Welcher von beiden soll dann benutzt werden?

Also entweder ein Stdkonstruktor in Base oder ein Konstuktoraufruf in der Initialisierungsliste von D sollten das Problem denke ich beheben.

Sag bescheid ob es geklappt hat, ich bin nimmer so fit was virtuelle Vererbung angeht und würde gerne wissen ob meine Vermutung richtig ist *g* (Ich habe es bisher nur für interfaces benutzt)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

3

13.01.2010, 10:52

Es is genauso wie xardias gesagt hat ;)

the[V]oid

Alter Hase

  • »the[V]oid« ist der Autor dieses Themas

Beiträge: 775

Wohnort: Aachen

  • Private Nachricht senden

4

13.01.2010, 11:15

Das Problem ist, dass ich in D den Konstruktor von Base nicht aufrufen kann, da dieser Aufruf, je nach dem, ob es sich nun um ein Sub1 oder um ein Sub2 handelt, unterschiedlich gestalten müsste (von den Parametern her).
Also doch ein Design-Fehler meinerseits?
<< an dieser Stelle ist eine Signatur verstorben >>

xardias

Community-Fossil

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

5

13.01.2010, 11:24

Zitat von »"the[V«

oid"]Das Problem ist, dass ich in D den Konstruktor von Base nicht aufrufen kann, da dieser Aufruf, je nach dem, ob es sich nun um ein Sub1 oder um ein Sub2 handelt, unterschiedlich gestalten müsste (von den Parametern her).
Also doch ein Design-Fehler meinerseits?

Japp. Virtuelle Vererbung sorgt dafür, dass der Konstruktor der gemeinsamen Basisklasse nur ein mal aufgerufen wird. Das ist quasi der ganze Sinn davon.

Das klingt nach einem ziemlich wirren Klassendesign. Beschreib mal was du vor hast, vielleicht kann man das anders eleganter lösen.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

13.01.2010, 11:31

Zitat von »"the[V«

oid"]Das Problem ist, dass ich in D den Konstruktor von Base nicht aufrufen kann, da dieser Aufruf, je nach dem, ob es sich nun um ein Sub1 oder um ein Sub2 handelt, unterschiedlich gestalten müsste (von den Parametern her).
Also doch ein Design-Fehler meinerseits?


Definitiv ein Designfehler, denn die virtuelle Vererbung sorgt dafür dass es in D nur ein Base Objekt gibt das Sub1 und Sub2 sich teilen. Zwei verschiedene Konstruktoraufrufe wären also ziemlicher Schwachsinn...

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

7

13.01.2010, 14:50

Es scheint ein regelrechter Meinungskonflikt zu sein, ob jetzt Mehrfachvererbung gut oder böse ist. Nicht ohne Grund hat ja Java und C# das Problem so gelöst, dass Mehrfachvererbung gar nicht oder nur mit abstrakten Klassen geht. Eiffel hingegen hat standardmässig so etwas, wie virtuelle Vererbung.
Das finde ich das schöne an C++ im Gegensatz zu anderen Sprachen. Es gibt dir die Chance selbst zu wählen, was man tun möchte. Man sollte sich halt einfach den Konsequenzen im klaren sein.

FalkT

Treue Seele

Beiträge: 125

Wohnort: AC

  • Private Nachricht senden

8

14.01.2010, 17:07

Zitat von »"drakon"«

Es scheint ein regelrechter Meinungskonflikt zu sein, ob jetzt Mehrfachvererbung gut oder böse ist.


Thema verfehlt !!!
Das Problem ist nicht Merfachvererbung, sondern der Diamond.
Der ist nicht Geschmackssache, sondern ein Design-Fehler.

the[V]oid

Alter Hase

  • »the[V]oid« ist der Autor dieses Themas

Beiträge: 775

Wohnort: Aachen

  • Private Nachricht senden

9

14.01.2010, 17:13

Diamond ganz pauschal ein Design-Fehler? O.o
Glaub ich kaum. Kann mir gut einige Fälle vorstellen, wo es Sinn macht.
<< an dieser Stelle ist eine Signatur verstorben >>

FalkT

Treue Seele

Beiträge: 125

Wohnort: AC

  • Private Nachricht senden

10

14.01.2010, 17:30

Zitat von »"the[V«

oid"]Diamond ganz pauschal ein Design-Fehler? O.o
Glaub ich kaum. Kann mir gut einige Fälle vorstellen, wo es Sinn macht.

Es geht mir um die Fälle, wo der Diamond zu einen Problem wird.

Oft reicht es natürlich, wenn man einen der beiden Parents nutzen kann und der andere total egal ist.

Werbeanzeige