Datenelemente der virtuellen Basisklasse

8

Warum wird empfohlen, keine Datenelemente in der virtuellen Basisklasse zu haben?

Was ist mit Funktionsmitgliedern? Wenn ich eine Aufgabe habe, die allen abgeleiteten Klassen gemeinsam ist, ist es in Ordnung, wenn die virtuelle Basisklasse die Aufgabe ausführt, oder sollte die abgeleitete Klasse von zwei Klassen abstammen - von der virtuellen Schnittstelle und der einfachen Basis, die die Aufgabe ausführen?

Danke.

    
jackhab 28.07.2009, 10:03
quelle

5 Antworten

11

In der Praxis sollten Sie die virtuelle Vererbung nur verwenden, um Schnittstellen zu definieren, die normalerweise mit Mehrfachvererbung verwendet werden, um sicherzustellen, dass nur eine Version der Klasse in der abgeleiteten Klasse vorhanden ist. Und reine Schnittstellen sind die sicherste Form der Mehrfachvererbung. Natürlich, wenn Sie wissen, was Sie tun, können Sie die Mehrfachvererbung verwenden, wie Sie möchten, aber es kann zu sprödem Code führen, wenn Sie nicht vorsichtig sind.

Der größte Nachteil bei der virtuellen Vererbung ist, wenn ihre Konstruktoren Parameter übernehmen. Wenn Sie Parameter an den Konstruktor einer virtuellen Basisklasse übergeben müssen, zwingen Sie alle abgeleiteten Klassen, den Konstruktor explizit aufzurufen (sie können sich nicht auf eine Basisklasse verlassen, die den Konstruktor aufruft).

Der einzige Grund, den ich für Ihre ausdrückliche Beratung sehen kann, ist, dass Daten in Ihrer virtuellen Basisklasse möglicherweise Konstruktorparameter erfordern.

Bearbeiten Ich habe nach Martins Kommentar ein wenig zu Hause gearbeitet, danke Marin. Die erste Zeile stimmt nicht ganz:

  

Als eine Praxis sollten Sie nur verwenden   virtuelle Vererbung zum Definieren   Schnittstellen wie sie normalerweise verwendet werden   mit Mehrfachvererbung sicherstellen   dass nur eine Version der Klasse ist   in der abgeleiteten Klasse vorhanden.

Die virtuelle Vererbung macht keinen Unterschied, wenn die Basisklasse eine reine Schnittstelle ist (abgesehen von etwas anderen Compilerfehlern in vc8, wenn nicht alle Methoden implementiert sind). Es macht nur einen wirklichen Unterschied, wenn die Basisklasse Daten enthält. In diesem Fall endet die Raute mit einer Raute und nicht mit einer U-Form

%Vor%

Im virtuellen Fall teilen sich B und C dieselbe Kopie von A.

Ich stimme jedoch allem anderen überein, dass reine Schnittstellen die sicherste Form der Mehrfachvererbung sind, auch wenn sie keine virtuelle Vererbung erfordern. Und die Tatsache, dass Konstruktorparameter und virtuelle Vererbung ein Schmerz sind.

    
iain 28.07.2009, 11:31
quelle
2

Der wichtigste Ratschlag ist, einen Standardkonstruktor in der virtuellen Datenbank zu haben. Wenn Sie das nicht tun, dann muss jede abgeleitete Klasse (dh jede Unterklasse) die virtuelle Basis ctor explizit aufrufen, was dazu führt, dass wütende Kollegen an Ihre Bürotür klopfen ...

> %Vor%     
Marc Mutz - mmutz 28.07.2009 11:33
quelle
1

Ich habe diese Empfehlung noch nie gesehen.

Eine Klasse ist eine Menge eng verwandter Funktionen und Daten. Der Zweck einer Basisklasse besteht darin, einen gemeinsamen Satz von Funktionen und Daten zu haben, die von abgeleiteten Klassen wiederverwendet werden können.

Ich denke, dass die Beschränkung auf Datenelemente oder nicht-reine virtuelle Funktionen in Basisklassen die Menge der Wiederverwendung von Code reduziert, was auf lange Sicht zu weniger zuverlässigem Code führt.

    
David Coufal 28.07.2009 11:31
quelle
0

a) Mitglieder sollten privat sein - so können Sie Probleme bekommen, sie in abgeleiteten Klassen zu verwenden (also müssen Sie Getter- und Setter-Methoden hinzufügen, die Ihre Schnittstelle sprengen)

b) deklariere keine Dinge, die du gerade nicht benutzt - deklariere Variablen nur in Klassen, die auf sie zugreifen / sie benutzen

c) virtuelle Basisklassen sollten nur die Schnittstellen / virtuellen Methoden enthalten, nichts mehr

Ich hoffe, das hilft ein bisschen, auch wenn meine Gründe nicht perfekt und vollständig sind:)

ciao, Chris

    
3DH 28.07.2009 10:07
quelle
0

All-abtract-Basisklassen, die zum Simulieren von Schnittstellen in C ++ verwendet werden, sollten keine Datenelemente enthalten, da sie eine Schnittstelle beschreiben und der Instanzstatus ein Implementierungsdetail ist.

Außerdem können Basisklassen mit virtuellen Funktionen durchaus Datenelemente enthalten. Es gelten jedoch die üblichen Regeln:

  • mache sie so versteckt wie möglich und benutze Getter und Setter, wenn du Klasseninvarianten erhalten willst.
    (Es gibt hier eine Lücke: Wenn dem Member keine Invariante zugeordnet ist, d. H. Er kann zu jedem beliebigen Zeitpunkt einen beliebigen Wert annehmen, wird er möglicherweise öffentlich gemacht. Dies verweigert jedoch eine abgeleitete Klasse, die eine Invariante hinzufügt.
  • Design für Vererbung: Der Vertrag Ihrer Klasse sollte die Verantwortlichkeiten und Möglichkeiten einer abgeleiteten Klasse definieren, was sie zu welchem ​​Zweck überschreiben / überschreiben kann.
peterchen 28.07.2009 12:05
quelle

Tags und Links