Frage

http://en.wikipedia.org/wiki/Diamond_problem

Ich weiß, was es bedeutet, aber welche Schritte kann ich es vermeiden?

War es hilfreich?

Lösung

Ein praktisches Beispiel:

class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};

Beachten Sie, wie der Klasse D von beiden B erbt & C. Aber beide B & C erben von A. Das in 2 Kopien der Klasse führen A in der V-Tabelle enthalten sind.

Um dies zu lösen, müssen wir virtuelle Vererbung. Es ist die Klasse A, die praktisch vererbt werden muss. Also, das wird das Problem beheben:

class A {};
class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};

Andere Tipps

virtuelle Vererbung. Das ist, was es ist da.

Ich würde halten Sie sich an nur Mehrfachvererbung von Schnittstellen. Während Mehrfachvererbung von Klassen manchmal attraktiv ist, kann es auch verwirrend und schmerzhaft sein, wenn Sie regelmäßig auf sie verlassen.

Die Vererbung ist eine starke, starke Waffe. Verwenden Sie es nur, wenn Sie es wirklich brauchen. In der Vergangenheit war Diamant Erbe ein Zeichen, dass ich mit der Klassifizierung zu weit ging und sagte, dass ein Benutzer ein „Mitarbeiter“, aber sie sind auch ein „Widget Zuhörer“, sondern auch ein ...

In diesen Fällen ist es einfach, Mehrfachvererbung Fragen zu treffen.

Ich löste sie durch die Zusammensetzung und Zeiger zurück an den Eigentümer mit:

Bevor:

class Employee : public WidgetListener, public LectureAttendee
{
public:
     Employee(int x, int y)
         WidgetListener(x), LectureAttendee(y)
     {}
};

Nach:

class Employee
{
public:
     Employee(int x, int y)
         : listener(this, x), attendee(this, y)
     {}

     WidgetListener listener;
     LectureAttendee attendee;
};

Ja, Zugriffsrechte sind unterschiedlich, aber wenn man sich mit einem solchen Ansatz bekommen, ohne Code zu duplizieren, ist es besser, weil es weniger leistungsfähig ist. (Sie können die Stromversorgung sparen, wenn Sie keine andere Wahl haben.)

class A {}; 
class B : public A {}; 
class C : public A {}; 
class D : public B, public C {};

Dabei sind die Attribute der Klasse A zweimal in der Klasse D wiederholt, die mehr Speichernutzung macht ... So Speicher sparen wir ein virtuelles Attribut für alle vererbten Attribute der Klasse A zu machen, die in einer Vtable gespeichert werden.

Nun, die große Sache über den gefürchteten Diamanten ist, dass es ein Fehler, wenn er auftritt. Der beste Weg zu vermeiden, ist Ihre Vererbungsstruktur vorher herauszufinden. Zum Beispiel an einem Projekt, das ich arbeiten muß, Viewer und Editoren. Redakteure sind logische Subklassen von Zuschauern, aber da alle Zuschauer Subklassen sind - Textviewer, Viewer usw. Editor stammt nicht aus Viewers, so dass die endgültige Texteditor, Imageeditor Klassen ermöglicht, die Diamanten zu vermeiden

.

In Fällen, in denen der Diamant nicht vermeidbar ist, virtuelle Vererbung. Der größte Nachteil ist jedoch mit virtuellen Basen ist, dass der Konstruktor für die virtuelle Basis muss durch die meisten abgeleiteten Klassen aufgerufen werden, was bedeutet, dass eine Klasse, die praktisch leitet keine Kontrolle über die Konstruktorparameter hat. Auch das Vorhandensein einer virtuellen Basis neigt beim Gießen durch die Kette eine Leistung / Raum Strafe entstehen, obwohl ich nicht glaube, es ist viel von einer Strafe für mehr über die ersten.

Darüber hinaus können Sie immer die Diamant verwenden, wenn Sie explizit sind, welche Basis die Sie verwenden möchten. Manchmal ist es der einzige Weg.

Ich würde eine bessere Klasse Design vorschlagen. Ich bin sicher, es gibt einige Probleme, die am besten durch Mehrfachvererbung gelöst werden, aber überprüfen, um zu sehen, ob es eine andere Möglichkeit ist zuerst.

Wenn nicht, verwenden virtuelle Funktionen / Schnittstellen.

Verwenden Sie Vererbung durch Delegation. Dann wird zeigen beide Klassen an einer Basis A, sondern haben Methoden zu implementieren, die auf A. umleiten Es hat den Nebeneffekt der geschützten Mitglieder von A Drehen in „private“ Mitglieder in B, C und D, aber jetzt nicht wahr muß virtuell, und Sie haben keinen Diamanten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top