46 Stimmen

Kopieren eines polymorphen Objekts in C++

Ich habe die Basisklasse Base von dem abgeleitet wird Derived1 , Derived2 y Derived3 .

Ich habe eine Instanz für eine der abgeleiteten Klassen erstellt, die ich als Base* a . Ich muss nun eine tiefe Kopie des Objekts erstellen, die ich als Base* b .

Soweit ich weiß, ist der normale Weg, eine Klasse zu kopieren, die Verwendung von Kopierkonstruktoren und das Überladen von operator= . Da ich jedoch nicht weiß, ob a ist vom Typ Derived1 , Derived2 o Derived3 Ich kann mir nicht vorstellen, wie man entweder den Kopierkonstruktor oder operator= . Der einzige Weg, den ich mir vorstellen kann, um dies sauber zu machen, ist, etwas wie zu implementieren:

class Base
{
public:
  virtual Base* Clone() = 0;

};

und das Gerät Clone in der abgeleiteten Klasse wie in:

class Derivedn : public Base
{
public:
  Base* Clone() 
  {
    Derived1* ret = new Derived1;
    copy all the data members
  }
};

Java neigt zur Verwendung von Clone Gibt es eine bessere Möglichkeit, dies mit C++ zu tun?

46voto

Michael Anderson Punkte 65535

Dies ist immer noch die Vorgehensweise in C++ für polymorphe Klassen, aber Sie müssen die explizite Kopie von Mitgliedern nicht durchführen, wenn Sie einen Kopierkonstruktor (möglicherweise implizit oder privat) für Ihre Objekte erstellen.

class Base
{
public:
  virtual Base* Clone() = 0;
};

class Derivedn : public Base
{
public:
  //This is OK, its called covariant return type.
  Derivedn* Clone() 
  {
    return new Derivedn(*this);
  }
private:
  Derivedn(const Derivedn&) : ... {}
};

0voto

Jon Garbe Punkte 25
template <class T>
Base* Clone (T derivedobj) {
  T* derivedptr = new T(derivedobj);
  Base* baseptr = dynamic_cast<Base*>(derivedptr);
  if(baseptr != NULL) {
    return baseptr;
  }
  // this will be reached if T is not derived from Base
  delete derivedptr;
  throw std::string("Invalid type given to Clone");
}

Das einzige, was diese Funktion von den abgeleiteten Klassen verlangt, ist, dass ihr Kopierkonstruktor öffentlich zugänglich ist.

0voto

Shwalala Punkte 3

Ich habe einige Antworten gesehen, die eine Vorlagenfunktion zum Klonen von Objekten verwenden. Ich möchte Ihnen zeigen, wie das nicht funktioniert. Betrachten Sie den folgenden Code:

Dies ist ein Sonderfall, der auftritt, wenn Objekte von einer Container mit Base-Objekten . Die Funktion gibt einen Zeiger auf die Base zurück, auch wenn obj vom Typ Derived ist. Die Schablone funktioniert nur, wenn sie von einem Objekt aufgerufen wird, das keinem Casting unterzogen wurde.

#include <iostream>
#include <memory>
#include <vector>

class Base{
public:
    virtual void foo(){}
};

class Derived : public Base{};

template<typename T>  std::shared_ptr<T> foo(const T& obj){
    std::cout << "obj is of type: " << typeid(obj).name() << std::endl;
    std::cout << "T is of type: " << typeid(T).name() << std::endl;
    std::cout << std::endl;
    return std::make_shared<T>(obj); // returns Base pointer
}

int main()
{
    std::vector<std::shared_ptr<Base>> vec {std::make_shared<Base>(), std::make_shared<Derived>()};
    for(auto c: vec)
        foo(*c);

    return 0;
}

/* OUTPUT:
obj is of type: 4Base
T is of type: 4Base

obj is of type: 7Derived
T is of type: 4Base

*/

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X