Ist dies der richtige Weg, um pimpl wth unique_ptr und move-semantics in C ++ 11 zu implementieren

9

Ich habe noch kein pimpl-Beispiel gesehen, das sowohl unique_ptr als auch move-semantics verwendet.

Ich möchte eine CHelper-Klasse zu STL-abgeleiteten Containern hinzufügen und pimpl verwenden, um zu verbergen, was CHelper tut.

Sieht das richtig aus?

Derived.h

%Vor%

'

Helfer.h

%Vor%

Helper.cpp

%Vor%     
John Balcom 26.06.2012, 16:35
quelle

1 Antwort

3

Da das einzige Mitglied von CHelper ein unique_ptr ist und die Standardimplementierung von copy die Kopie der Basen und der Mitglieder aufruft, ruft die Standardimplementierung für move auf Wenn Sie move der Basen und Mitglieder verschieben, müssen Sie die CHelper ctors und assigns nicht überschreiben. Lass den Standard einfach seine Arbeit machen. Sie rufen einfach den entsprechenden unique_ptr-Move-Konstruktor und -Operator auf.

Über das Zusammenstellen von CHelper und a set<...> zu einem CDerived ... das ist kein "kanonisches Design" ( set ist keine OOP-Klasse ..., und CHelper ist es auch nicht) aber kann funktionieren, wenn Sie richtig verwendet werden (versuchen Sie nicht, CDerived einem CHelper* ad call delete darauf zuzuweisen, oder Sie werden in Tränen enden). Es gibt einfach nicht genug Informationen, um zu verstehen, was sie vorhaben.

Wenn das Problem ist "Ich möchte, dass Chelper auch kopieren kann", dann sollten Sie wahrscheinlich besser sein einem Idiom wie folgt folgen ( #include und using namespace auseinander ...)

%Vor%

Natürlich können Sie Deklarationen und Implementierungen nach Belieben trennen.

EDIT folgenden John Balcom Kommentare.

Ja, natürlich ändert sich der Code, aber nicht in seiner Substanz. Sie können nur struct impl; in CHelper weiterleiten (so dass unique_ptr eine Bedeutung hat), dann deklarieren struct CHelper::impl woanders (möglicherweise in der CPP-Datei, wo alle CHelper-Implementierungen ausgeführt werden).

Hier ist nur zu beachten, dass in der CPP-Datei CHelper :: impl sowohl Konstruktor als auch Destruktor definiert sein müssen, um eine kohärente unique_ptr-Instantiierung (die den impl-Destruktor aufrufen muss) innerhalb der CPP-Datei zu haben. Andernfalls besteht bei einigen Compilern das Risiko, dass in allen Dateien, die die CHelper-Deklaration enthalten, ein Fehler "unvollständige Typverwendung" auftritt.

Über den zweiten Punkt (abgeleitet von std::set ) ist dies ein umstrittener Aspekt der C ++ Programmierung. Aus Gründen, die für C ++ selbst nicht relevant sind, aber mit der objektorientierten Programmierschule, bedeutet "inhertance" "ist ein" und "ist ein" bedeutet "Objekt-Substitution möglich" . Da das Löschen eines Objekts über einen Basiszeiger UB ist, wenn das Basis-dtor nicht virtuell ist, also die Objektsoubstitution UB macht, verweigern die OOP-Schule als Dogma die Vererbung der Klasse, die kein virtuelles dtor hat, und wegen des Weges Sie waren erzogen worden, als sie anfingen zu programmieren, sie fangen an, ihre Flamme auf dich zu spucken, wenn du das tust.

Für mich ist das kein Problem in Ihrem Design, aber ihr Fehler zu verstehen, dass C ++ Vererbung nicht " ist ein " bedeutet, sondern " ist wie " und tut es auch nicht implizieren Objektersetzung (für mich ist es ihre Schuld zu denken, jede C ++ Klasse ist ein OOP-Objekt, nicht mit einem Werkzeug, um etwas Nützliches für Sie zu tun, schauen Sie einfach hier oder hier , wenn Sie mehr Klarheit über meine Position haben wollen: Objektersetzung in C ++ ist nicht für "Objekt", sondern Methode für Methode, da jede Methode virtuell oder nicht unabhängig voneinander sein kann. Das heißt, vielleicht musst du mit diesen Leuten arbeiten, also ... bewerte Vor-und Nachteile, indem du ihnen bei der Ausübung ihrer eigenen Lieblingsreligion nicht folgst.

    
Emilio Garavaglia 26.06.2012 17:03
quelle

Tags und Links