C ++ - Klassenerweiterung

7

Gibt es eine Möglichkeit, einer Klasse neue Methoden hinzuzufügen, ohne die ursprüngliche Klassendefinition (d. h. kompilierte .lib-Klasse und entsprechende .h-Datei) wie die Klassenerweiterungsmethoden von C # zu ändern?

    
paul simmons 25.10.2009, 17:40
quelle

9 Antworten

15

Nein. C ++ hat keine solche Fähigkeit.

Wie in anderen Antworten erwähnt, sind die üblichen Problemumgehungen:

  • Definieren Sie eine abgeleitete Klasse, vielleicht mit einer Factory, um die eigentliche Implementierungsklasse zu verbergen
  • Definieren Sie eine Dekorierer Klasse
  • Definieren Sie Funktionen für Instanzen der Klasse
Kristopher Johnson 25.10.2009, 17:42
quelle
11

Nein, das ist in C ++ nicht möglich.

Wenn Sie so etwas erreichen möchten, haben Sie 2 Möglichkeiten,

  • Sie können von der Klasse erben (wenn dies eine Option ist, ist sie möglicherweise nicht zulässig, da die Klasse möglicherweise nicht für die Vererbung geschrieben wurde)
  • Sie können Ihre eigene Wrapper-Klasse schreiben, die dieselbe Schnittstelle + Ihre neuen Methoden hat und delegieren Sie an die, die Sie erweitern möchten.

Ich bevorzuge den Delegationsansatz.

    
Glen 25.10.2009 17:42
quelle
5

C # -Klassenerweiterungsmethoden sind meist syntaktischer Zucker. Sie erhalten die gleiche Funktionalität mit freien Funktionen (d. H. Funktionen mit einer Referenz oder einem konstanten Bezug auf Ihre Klasse als ihr erster Parameter). Da dies gut für die STL funktioniert, warum nicht für Ihre Klasse?

    
Pontus Gagge 25.10.2009 17:47
quelle
3

In C ++ können Sie freie Funktionen verwenden, aber manchmal funktionieren Erweiterungsmethoden besser, wenn Sie viele Funktionen verschachteln. Sehen Sie sich diesen C # -Code an:

%Vor%

Wenn wir das in C ++ mit der free-Funktion schreiben würden, würde es so aussehen:

%Vor%

Das ist nicht nur schwer zu lesen, es ist auch schwierig zu schreiben. Der übliche Weg, dies zu lösen, besteht darin, eine so genannte Pipable-Funktion zu erstellen. Diese Funktionen werden erstellt, indem der Operator | pipe (der eigentlich nur der Operator oder ist) überladen wird. So könnte der obige Code so geschrieben werden:

%Vor%

Das ist viel einfacher zu lesen und zu schreiben. Viele Bibliotheken verwenden die Pipable-Funktion für Bereiche, sie könnten jedoch auch auf andere Klassen erweitert werden. Boost verwendet es in ihrem Bereich Bibliothek, pstade Ofen verwendet es, und auch dieses C ++ linq Bibliothek verwendet es auch.

Wenn Sie Ihre eigene Pipable-Funktion schreiben möchten, erklären Sie, wie dies zu tun ist hier . Andere Bibliotheken stellen jedoch Funktionsadapter zur Verfügung, um es einfacher zu machen. Pstade hat einen pipable Adapter und linq stellt den range_extension -Adapter bereit, um mindestens für Bereiche eine pipable-Funktion zu erstellen.

Mit linq erstellst du zuerst deine Funktion als Funktionsobjekt wie folgt:

%Vor%

Dann initialisieren Sie die Funktion mit einer statischen Initialisierung wie folgt:

%Vor%

Dann können Sie Ihre pipable Funktion wie folgt verwenden:

%Vor%     
Paul Fultz II 14.02.2013 17:47
quelle
1

Im Allgemeinen nicht. Wenn die Bibliothek jedoch keine Instanzen der Klasse erstellt, die Ihre Erweiterung erfordern, und Sie alle Bereiche in der Anwendung ändern können, die eine Instanz der Klasse erstellen und Ihre Erweiterungen erfordern, können Sie folgendermaßen vorgehen:

  • Erstellen Sie eine Factory-Funktion, die an allen Stellen aufgerufen wird, die eine Instanz der Klasse erfordern, und gibt einen Zeiger auf die Instanz zurück (google für Design Patterns Factory , ...).
  • Erstellen Sie eine abgeleitete Klasse mit den gewünschten Erweiterungen.
  • Lassen Sie die Factory-Funktion die abgeleitete Klasse anstelle der ursprünglichen Klasse zurückgeben.

Beispiel:

%Vor%
  • Wann immer Sie auf die Erweiterungen zugreifen müssen, müssen Sie natürlich die ursprüngliche Umwandlung in die abgeleitete Klasse umwandeln.

Dies ist ungefähr, wie man die von Glen vorgeschlagene "inherit" -Methode implementiert. Glens "Wrapper-Klasse mit der gleichen Schnittstelle" -Methode ist auch aus theoretischer Sicht sehr nett, hat aber leicht andere Eigenschaften, die es weniger wahrscheinlich machen, in Ihrem Fall zu arbeiten.

    
mh. 25.10.2009 19:55
quelle
1

Es gibt einen Weg, wie es gemacht werden kann. Und das ist, indem Sie Ihre Anforderungen etwas entspannen. In C ++ wird oft gesagt, dass die Schnittstelle einer Klasse nicht nur aus ihren Elementfunktionen besteht, sondern aus allen Funktionen, die an der Klasse arbeiten.

Das heißt, Nichtmitgliedsfunktionen, denen die Klasse als Parameter zugewiesen werden kann, sollten als Teil ihrer Schnittstelle betrachtet werden.

Zum Beispiel sind std::find() oder std::sort() Teil der Schnittstelle von std::vector , obwohl sie keine Mitglieder der Klasse sind.

Und wenn Sie diese Definition akzeptieren, können Sie eine Klasse einfach erweitern, indem Sie Nichtmitgliedsfunktionen hinzufügen.

    
jalf 26.10.2009 01:16
quelle
0

Sie können der Klassendatei, die binär ist, keine Methoden oder Daten hinzufügen. Sie können jedoch den Objekten dieser Klasse Methoden und Daten (Funktionalität und Status) hinzufügen, indem Sie Erweiterungsklassen schreiben. Dies ist nicht direkt und erfordert Meta-Object-Protocol und Interface-basierte Programmierung. Sie müssen eine Menge dafür tun, um dies in C ++ zu erreichen, da es Reflection nicht standardmäßig unterstützt. Wenn Sie in einer solchen Implementierung nach der Schnittstelle suchen, die von Ihrer neuen Erweiterungsklasse über den ursprünglichen Klassenobjektzeiger implementiert wurde, gibt die Metaobjektimplementierung diesen Schnittstellenzeiger über das Metaklassenobjekt für die Erweiterungsklasse zurück, die zur Laufzeit erstellt wird. So funktionieren viele anpassbare (pluginbasierte) Software-Anwendungs-Frameworks. Sie müssen jedoch daran denken, dass viele andere MOP-Mechanismen geschrieben werden müssen, um Metaobjekte für alle Klassen zu erstellen, die Wörterbücher verwenden, in denen die Objektbeziehungen beschrieben werden, und die richtigen Schnittstellenzeiger für die ursprünglichen und erweiterten Klassenobjekte angeben. CATIA V5 von Dassault Systèmes ist in einer solchen Architektur namens CAA V5 geschrieben, in der Sie vorhandene Komponenten erweitern können, indem Sie neue Erweiterungsklassen mit der gewünschten Funktionalität schreiben.

    
Sharjith N. 14.09.2011 17:48
quelle
-2

Sorry, nein. Sobald Ihr Code in obj ist, können Sie ihn nicht ändern. Wenn dies in VC getan werden kann, würden teilweise Klassen unterstützt werden. Es gibt jedoch eine Ausnahme: Operatormethoden können mit globalen Funktionen erweitert werden, ähnlich wie cout & lt; & lt; ist in AWL implementiert.

    
Sheng Jiang 蒋晟 25.10.2009 17:46
quelle
-3

Sicher kannst du:

%Vor%

Das heißt aber nicht, dass es der beste Ansatz ist.

    
Nikolai Fetissov 25.10.2009 17:52
quelle

Tags und Links