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?
Nein. C ++ hat keine solche Fähigkeit.
Wie in anderen Antworten erwähnt, sind die üblichen Problemumgehungen:
Nein, das ist in C ++ nicht möglich.
Wenn Sie so etwas erreichen möchten, haben Sie 2 Möglichkeiten,
Ich bevorzuge den Delegationsansatz.
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?
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:
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%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:
Beispiel:
%Vor%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.
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.
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.
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.
Sicher kannst du:
%Vor%Das heißt aber nicht, dass es der beste Ansatz ist.
Tags und Links class c++ extension-methods