2016-08-02 6 views
2

Ich möchte die Standardfunktionalität des Kopierzuweisungsoperators verwenden, bin aber in der Lage, einige zusätzliche Aufgaben im Rahmen der Operation auszuführen. So würde die Grundlagen Form wie folgt aussehen:C++ - Standard-Kopierzuweisungsoperator vom überladenen Kopierzuweisungsoperator

class Test 
{ 
    void operator=(Test& that) 
    { 
     *this = that; //do the default copy operation 
     this->foo() //perform some other tasks 
    } 
}; 

leicht durch Erstellen einer Kopie() Funktion erfolgen Dies könnte aber es wäre schön, die Sauberkeit des „=“ Betrieb zu bewahren.

Antwort

3

Sie könnten eine Basisimplementierung Klasse und Delegierter an der Basis operator= aus der Unterklasse

// Fill this class with your implementation. 
class ClsImpl { 
    // some complicated class 
protected: 
    ~ClsImpl() = default; 
}; 

class Cls : public ClsImpl { 
public: 
    Cls& operator=(const Cls& other) { 
    if (this == &other) { return *this; } 
    // assign using the base class's operator= 
    ClsImpl::operator=(other); // default operator= in ClsImpl 
    this->foo(); // perform some other task 
    return *this; 
    } 
}; 
+2

Warum Sie verwenden 'static_cast' die Basisklassenimplementierung zu zwingen Aufruf statt nur explizit über' ClsImpl :: operator = (anderen) aufgerufen wird; '. Wenn 'ClsImpl' nur eine Möglichkeit ist, die Kopierzuweisungsfunktionalität zu delegieren, sollten Sie wahrscheinlich private Vererbung verwenden, um implizite Konvertierungen zu verhindern und das Risiko des Slicings einzuführen. –

+1

@CaptainObvlious sie sind das gleiche, aber das Auslassen der Besetzung ist ein Gewinn, ich stimme zu. Private Vererbung wäre großartig, wenn es nicht auch wahrscheinlich eine Tonne 'using'-Deklarationen erfordern würde, um alle Mitgliedsfunktionen der Basisklasse verfügbar zu machen. –

+0

Yeah viele 'using' Aussagen würden saugen. Wenn der Kopierkonstruktor und der Kopierzuweisungsoperator in der Basisklasse geschützt wären, würde dies ohnehin für das Schneiden sorgen. –

0

Eine Möglichkeit ist, verwenden wieder von der abgeleiteten Klasse abzuleiten, die Post-Kopie Logik zu liefern.

#include <iostream> 


// a wrapper class to provide custom copy actions 

template<class Base> 
struct CopyActions : Base 
{ 
    using base_class = Base; 
    using CopyActions::base_class::base_class; 

    // copy operator will call the base and then perform custom action 

    CopyActions& operator=(const CopyActions& r) { 
     base_class::operator=(r); 
     onCustomCopy(r, *this); 
     return *this; 
    } 
}; 

// a class to notify us when a copy takes place, without having to write 
// custom copy operators 
struct copy_sentinel 
{ 
    copy_sentinel operator=(const copy_sentinel&) { 
     std::cout << "copying " << name << '\n'; 
     return *this; 
    } 
    const char* name; 
}; 


int test_count = 0; 

// a model base class 
struct MyBase 
{ 
    int base_count = test_count++; 
    copy_sentinel base_s { "MyBase" }; 
}; 

// a model derived class containing only logic 
struct MyDerived : MyBase 
{ 
    int derived_count = test_count++; 
    copy_sentinel base_s { "MyDerived" }; 
}; 

// a custom copy action (free function) 
void onCustomCopy(const MyDerived& from, MyDerived& to) 
{ 
    std::cout << "custom copy action\n"; 
} 

// our derived class with custom copy actions 
using SuperDerived = CopyActions<MyDerived>; 

// test 
int main() 
{ 
    SuperDerived a; // 0, 1 
    SuperDerived b; // 2, 3 

    // prove initial values 
    std::cout << a.base_count << ", " << a.derived_count << std::endl; 

    // perform copy and report actions 
    a = b; 

    // prove a copy occurred 
    std::cout << a.base_count << ", " << a.derived_count << std::endl; 
} 

erwartete Ergebnisse:

0, 1 
copying MyBase 
copying MyDerived 
custom copy action 
2, 3 
Verwandte Themen