Zusammensetzung: Verwenden von Merkmalen, um Weiterleitungsfunktionen zu vermeiden?

8

Nehmen wir an, wir haben zwei Klassen, A und B . Bei Verwendung der Komposition zum Modellieren einer "has-a" oder "is -implementierten-in-terms-of" Beziehung (z. B. B has-a A ), einer der Nachteile gegenüber der Vererbung ist, dass B nicht die öffentliche Funktionalität von A enthält, die sie benötigt. Um Zugriff auf die öffentlichen Funktionen von A s zu erhalten, ist es notwendig, Weiterleitungsfunktionen bereitzustellen (im Gegensatz zur Vererbung, wobei B alle A s öffentlichen Funktionen erbt).

Um ein konkreteres Beispiel zu geben, nehmen wir an, wir haben ein Person , das hat-a ContactInfo :

%Vor%

Ich ignoriere alle Mängel im Design (es ist nur ein künstliches Beispiel, um meine Frage unten zu demonstrieren), ich musste mühsam die genauen Funktionssignaturen von ContactInfo in Person replizieren. In einem komplexeren Beispiel könnte es viele solcher Funktionen und viele Schichten von zusammengesetzten Klassen geben, was zu viel Codeverdoppelung mit allen üblichen Wartungsproblemen führt und fehleranfällig ist, usw.

Dies ist jedoch die empfohlene Vorgehensweise zum Modellieren von "has-a" oder "is -implementierten-in-terms-of" gemäß Quellen wie z. B. Artikel 38 von Meyers effektivem C ++ und Punkt 24 von Sutters außergewöhnlichem C ++ ( Link ).

Während ich dies erforschte, stieß ich auf diesen Wikipedia-Artikel , der das gleiche Thema behandelt. Am Ende des Artikels wird Folgendes vorgeschlagen:

  

Ein Nachteil der Verwendung von Komposition anstelle von Vererbung ist, dass alle   der Methoden, die von den zusammengesetzten Klassen zur Verfügung gestellt werden   implementiert in der abgeleiteten Klasse, auch wenn sie nur weiterleiten   Methoden. [...] Dieser Nachteil kann durch die Verwendung von Merkmalen vermieden werden.

Ich bin ziemlich neu im Begriff der Merkmale und mit allem, was ich gelesen habe, finde ich es schwierig, mich auf die obige Aussage zu beziehen. Meine Frage lautet daher: Wie würde man Traits verwenden, um die Weiterleitung von Funktionen mit Komposition zu vermeiden? Eine Antwort basierend auf meinem Beispiel ( Person und ContactInfo ) wäre ideal.

BEARBEITEN: Nur um einige der Antworten zu klären, bin ich mir der privaten Vererbung als Alternative zur Komposition für die Modellierung von "is-implemented-in-terms-of" bewusst ". Meine Frage geht nicht darum, es geht speziell um die Bedeutung der Aussage von Wikipedia bezüglich der Eigenschaften. Ich frage nicht nach Alternativen zur Komposition. Ich habe meine Frage präzisiert, um klarer zu machen, dass ich darum gebeten habe.

    
JBentley 04.01.2014, 10:47
quelle

4 Antworten

1

Zunächst sollte ich erwähnen, dass Eigenschaften in C ++ / STL und Sprachen wie PHP, Lasso usw. verschieden sind. Es sieht so aus, als ob der Artikel aus Wikipedia PHP-ähnliche Merkmale beschreibt, da C ++ / STL-Merkmale nicht für polymorphe Wiederverwendung ausgelegt sind (Wir sprechen über Code-Wiederverwendung mit polymorphem Verhalten, nicht wahr?). Sie wurden entwickelt, um die Deklaration von Vorlagenklassen zu vereinfachen.

Traits werden in einigen Sprachen verwendet, die keine Mehrfachvererbung unterstützen (PHP, Lasso usw.). Eigenschaften erlauben es, Mehrfachvererbung zu "emulieren" (aber Mehrfachvererbung und Eigenschaften sind nicht genau gleich).

Im Gegensatz dazu unterstützt C ++ keine PHP-Traits, unterstützt aber mehrfache Vererbung. Wenn man also von C ++ spricht, dann wird die merkmalsähnliche Lösung etwa so aussehen:

%Vor%

Also, um Ihre Frage zu beantworten

  

Wie sollte man Traits verwenden, um die Weiterleitung von Funktionen zu vermeiden?   Zusammensetzung?

1) Eigenschaften vermeiden nicht das Weiterleiten von Funktionen mit Komposition, da Eigenschaften unabhängig von der Komposition funktionieren. (Der Artikel aus Wikipadia täuscht ein wenig über die Beziehung zwischen Eigenschaften und Zusammensetzung)

2) PHP / Lasso-ähnliche Merkmale können teilweise in C ++ mit Mehrfachvererbung emuliert werden.

    
Alex Antonov 04.01.2014, 16:19
quelle
1

Vielleicht können Sie private Vererbung versuchen:

%Vor%

Sie sollten jedoch auf die in dieser FAQ :

  

Es gibt auch einige Unterschiede:

     
  • Die Simple-Composition-Variante wird benötigt, wenn Sie mehrere Engines pro Auto
  • enthalten möchten   
  • Die private Vererbungsvariante kann unnötige mehrfache Vererbung einführen
  •   
  • Die private Vererbungsvariante ermöglicht es den Mitgliedern von Car, ein Auto * in eine Engine *
  • umzuwandeln   
  • Die private Vererbungsvariante erlaubt den Zugriff auf die geschützten Mitglieder der Basisklasse
  •   
  • Die private Vererbungsvariante erlaubt Car, die virtuellen Funktionen von Engine zu überschreiben
  •   
  • Die private Vererbungsvariante macht es etwas einfacher (20 Zeichen im Vergleich zu 28 Zeichen), Car eine start () -Methode zu geben   Das ruft einfach zur start () -Methode der Engine
  • auf   

Sonst scheint das Beispiel der bereitgestellten Komposition mit Ihrem identisch zu sein. Das Klicken auf den Merkmal-Link im Wikipedia-Artikel lieferte keine C ++ - Artikel, und der Link in den Referenzen scheint ungefähr type traits zu sein. Ich konnte nicht finden, wie type traits etwas mit Ihrem Szenario zu tun hat.

    
user1508519 04.01.2014 11:06
quelle
1

Der Artikel spricht über Vererbung mit Interface ,

in der Tat sagt es, dass das Objekt einige Signaturen respektieren muss.

-Typ-Merkmale können verwendet werden, um zu überprüfen, ob die Signatur korrekt ist, und an die entsprechende Funktion zu senden

Zum Beispiel warten einige STL-Algorithmen auf den Typ Iterator , Diese Iteratoren erben jedoch nicht von class Iterator , sondern müssen einen Vertrag bereitstellen ( operator ++() , operator !=(rhs) , operator*() ).

mit dem Artikelbeispiel:

  • class Player - der kann
  • verschieben
  • Klassengebäude - die nicht verschieben können

Und Code:

%Vor%     
Jarod42 04.01.2014 11:39
quelle
0

AFAIK eine Merkmalsklasse ist etwas wie das Folgende:

%Vor%

Das ist: eine kompilierte Template-Klasse, in der Sie Ihre Delegate-Methoden implementieren (und / oder spezialisieren) können, um alles weiterzuleiten, was Sie benötigen, ohne (aus welchem ​​Grund auch immer) wiederkehrend auf Vererbung.

Ссылка

    
Marco A. 04.01.2014 11:26
quelle