deep copy and dynamic cast unique_ptr - c++

Suppose I have a class like the following:
class A { virtual ~A(); ... }
class B : public A { ... }
class C : public A { ... }
I also have a vector of unique_ptr which is declared this way:
std::vector<std::unique_ptr<A>> vec;
Assume vec is populated with unique_ptr to objects of derived class. What should I do if I want a deep copy of any of the vector elements, either b or c, and let a base class unique_ptr pointing to it? Originally I was doing things like
std::unique_ptr<A> tmp = std::make_unique<A>(*b);
I don't think this is correct.

One possible solution is to declare a virtual cloning method in the base class and override it for each subclass:
class A {
virtual ~A() {}
virtual std::unique_ptr<A> clone() const = 0;
}
class B : public A {
std::unique_ptr<A> clone() const override {
return std::unique_ptr<A>(new B(*this));
}
};
Edit:
An usage example:
void f(const A& original) {
std::unique_ptr<A> copy = original.clone();
// Here, copy points to an instance of class B.
}

Related

Is it possible to create an instance of a class within the same class?

Say I have a class:
class Foo{
public:
Foo(){
}
//Is it possible to create a function like this:
virtual Foo* createOb(){
//Should create a new Foo,Bar or Fiz, depending on the actual object type.
}
}
class Bar: public Foo{
public:
Bar(){
}
}
class Fiz: public Foo{
public:
Fiz(){
}
}
Is it possible to have a method createOb() in the base class, so when createOb() is called on an instance of one of the derived classes, that an instance of the derived class is created ?
Yes, it can be done, using CRTP.
Bu first, returning a raw pointer obtained from new is very dangerous. In c++ raw pointers should be used only when they do not have ownership of the pointed object. So I took the liberty to use unique_ptr:
struct Base {
virtual auto create_obj() -> std::unique_ptr<Base>
{
return std::unique_ptr<Base>{};
}
};
// abstract works too:
struct Base {
virtual auto create_obj() -> std::unique_ptr<Base> = 0;
};
template <class Derived>
struct Base_crtp : Base {
auto create_obj() -> std::unique_ptr<Base> override /* final */
{
return std::unique_ptr<Base>{new Derived{}};
}
};
struct D1 : Base_crtp<D1>
{
};
struct D2 : Base_crtp<D2>
{
};
And then:
auto b1 = std::unique_ptr<Base>{new D1{}};
auto b2 = std::unique_ptr<Base>{new D2{}};
auto new_d1 = b1->create_obj();
auto new_d2 = b2->create_obj();
Definitely YES!!!
When a method is declared virtual in base class, and called through the derived class object, then the derived class function gets called (Read vprt, vtable concept in c++).
#include <iostream>
using namespace std;
class A{
public:
virtual A* getobj(){
return new A();
}
};
class B: public A{
public:
B(){cout<<"B constructor"<<endl;}
virtual A* getobj(){
return new B();
}
};
int main()
{
A *a = new B();
A *second = a->getobj();
return 0;
}
In the above code, we are calling the getobj() function using class B's object.
Here the constructor of class B is called twice.
first, for new B() in main
secondly for getobj function call which again creates object of B
This is not an optimal solution, but it works.
In your .h
class Foo{
public:
Foo();
virtual Foo* createOb();
};
class Bar: public Foo{
public:
Bar();
};
class Fiz: public Foo{
public:
Fiz();
};
In your .cpp
#include "Header.h"
Foo::Foo() {}
Foo* Foo::createOb(){
if (dynamic_cast<Bar*>(this)) {
return new Bar();
}
else if (dynamic_cast<Foo*>(this)) {
return new Foo();
}
return nullptr;
}
Bar::Bar() {}
Fiz::Fiz() {}
As already suggested please consider a pure virtual method
No, this is not possible with "pure" inheritance. The classes must override createOb() member function in order to support cloning.
You can see why this is not possible by considering separate compilation of classes. An implementation of one-fits-all createOb() member function must be completed in isolation from Bar and Fiz, making it impossible for the base to know the type of its subclasses.
An implementation with a pure virtual function in the base is very common, though.
Another approach is to use Curiously Recurring Template Pattern (CRTP) to implement cloning. This article explains how it can be done.

Copy constructor for a class that has unique ptr of a Base class [duplicate]

This question already has answers here:
Copy constructor for a class with unique_ptr
(6 answers)
Closed 8 years ago.
When a class has a unique_ptr of a Base class what is a good way to implement the copy constructor.
Let me try to explain it with an example:
struct Base
{
virtual void doSth() = 0; // to make the class abstract.
};
struct Derived : public Base
{
virtual void doSth() override {}
};
struct Foo
{
std::unique_ptr<Base> bar;
Foo(const Foo& other) : bar(new Base(*other.bar)) // cant do it, its abstract.
{
bar = std::move(other.bar); // cant do it, reference object is modified.
}
};
Here as the class is abstract i cannot use its copy constructor. and also cannot use move on a constant reference ( we shouldnt do it actually, do not modify the object).
What I end up with is like so:
struct Base
{
virtual void doSth() = 0; // to make the class abstract.
};
struct Derived : public Base
{
virtual void doSth() override {}
Derived(const Base* b)
{
}
};
struct Foo
{
std::unique_ptr<Base> bar;
Foo(const Foo& other) : bar(new Derived(other.bar.get()))
{
}
};
However, it does not feel quite right, does it?
If you need to copy polymorphically, you will need to provide that in the interface of the type you are holding. Add a clone virtual function to Base and use that to create a copy that you can store in the copied Foo.
Other alternatives include not copying (delete the copy constructor) or use reference semantics (copies refer to the same object: change unique_ptr for shared_ptr) but neither of those alternatives really provide copies.
Here is the code for David's answer. Note that the virtual clone() is described in this answer.
#include <stdlib.h>
#include <cstddef>
#include <memory>
struct Base
{
virtual void doSth() = 0; // to make the class abstract.
virtual Base* clone() const = 0;
};
struct Derived : public Base
{
virtual void doSth() override {}
virtual Derived* clone() const {
return new Derived(*this);
}
};
struct Foo
{
std::unique_ptr<Base> bar;
Foo(const Foo& other) : bar(other.bar->clone()) // cant do it, its abstract.
{
}
};

copy constructor for a baseclasspointer to a subclass

I have a class(let's call it A) and I want to copy A. So I call A's copy constructor. A has a member of type B* which is a pointer of type B to one of his subclasses.(let's call them B with a number. (ie: B1, B5, ..))
Since I don't want to just copy the address, I call memberofA->copyconstructor from one of the subclasses. The copy constructor in the base class is called from within the copy constructor of the subclass. But is this possible or do i need to dynamic cast the pointer of type baseclass to the correct subclass the pointer is pointing too?
class A {
public:
A(const A& object) {
// what should i call here to deep copy member
}
private:
B* member //pointer to subclass of B
};
class B {
privatedatamamber
public:
B (const B& object) {
privatedatamember = object->getprivatedatamember();
}
};
class B1 : public B {
privatedatamember
public:
B1 (const B1& object) : B(object) {
privatedatamember = object->getprivatedatamember();
}
};
The approach I'd use is to give B an abstract method clone() returning a std::unique_ptr<B> which is implemented in every concrete class to return a copy, e.g.:
std::unique_ptr<B> D::clone() const {
return std::unique_ptr<B>(new D(*this));
}
When a deep copy is needed you can then just call clone().
Add a public function to B:
virtual B* Clone() = NULL;
B's subclasses must implement this (pure virtual function).
Here's an example:
B header:
virtual B* Clone() = 0; //public
B1 header:
virtual B* Clone();
B1 cpp:
B* B1::Clone()
{
return new B1(*this);
}
A:
A::A(const A& object) : member(object.member->Clone()) {
}

copying c++ abstract classes

Ok heres some code.
#include <iostream>
#include <deque>
using namespace std;
class A
{
public:
virtual void Execute()
{
cout << "Hello from class A" << endl;
}
};
class B: public A
{
public:
void Execute()
{
cout << "Hello from class B" << endl;
}
};
void Main()
{
deque<A *> aclasses = deque<A*>(0);
deque<A *> aclasses2 = deque<A*>(0);
A a1 = A();
B b1 = B();
aclasses.push_back(&a1);
aclasses.push_back(&b1);
aclasses[0]->Execute();
aclasses[1]->Execute();
//Now say I want to copy a class from aclasses to aclasses2
//while perserving it's identity and making it a seperate entity, without
//knowing the exact type it is.
aclasses2.push_back(new A(*aclasses[0]));
aclasses2.push_back(new A(*aclasses[1]));
//Now my problem show itself
for each(A * a in aclasses2)
a->Execute();
//Execute is called from the original class A both times.
}
Now you might say, why don't you just put the pointers from the first deque into the second deque? While I could but I need the data to be independent. Basically I want to be able to clone items from the first deque while preserving there identity and giving them there own data.
Now the current modified version
#include <iostream>
#include <deque>
using namespace std;
class A
{
public:
virtual void Execute()
{
cout << "Hello from class A" << endl;
}
virtual ~A() {} // don't forget the virtual destructor
virtual A* clone() const {
return new A(*this);
}
};
class B: public A
{
public:
void Execute()
{
cout << "Hello from class B" << endl;
}
virtual B* clone() { // return type is co-variant
return new B( *this );
}
};
void MainRUNNER()
{
deque<A *> aclasses = deque<A*>(0);
deque<A *> aclasses2 = deque<A*>(0);
A a1 = A();
B b1 = B();
aclasses.push_back(&a1);
aclasses.push_back(&b1);
aclasses[0]->Execute();
aclasses[1]->Execute();
//Now say I want to copy a class from aclasses to aclasses2
//while perserving it's identity and making it a seperate entity, without
//knowing the exact type it is.
aclasses2.push_back(aclasses[0]->clone());
aclasses2.push_back(aclasses[1]->clone());
//Now my problem show itself
for each(A * a in aclasses2)
a->Execute();
//Execute is called from the original class A both times.
}
The common pattern for handling that is through a virtual clone() method in the base class that will create a new object of the appropriate type:
struct base {
virtual ~base() {} // don't forget the virtual destructor
virtual base* clone() const {
return new base(*this);
}
};
struct derived : base {
virtual derived* clone() const { // return type is co-variant
return new derived( *this );
}
};
int main() {
std::auto_ptr<base> b1( new derived );
std::auto_ptr<base> b2( b1->clone() ); // will create a derived object
}
You need to provide a virtual copy constructor – usually this is a method called clone – which is overridden in each class to return the correct type:
class A {
virtual A* clone() {
return new A();
}
};
class B : public A {
void A* clone() {
return new B();
}
};
The methods can of course be arbitrarily complex in order to copy the whole state.
Of course, this leaks rather a lot of memory. Use appropriate smart pointers instead of raw pointers (e.g. std::shared_ptr if your compiler supports it, boost::shared_ptr otherwise).
You have new A(...) way down there. What gets called is A's copy constructor (created implicitly by the compiler.
What you want is a clone method. See here. It recaps the appropriate item from the excellent C++ Coding Standards book. Below is a shameless copy of the final solution, which also shows a nice use of the NVI idiom to avoid the slicing problem.
class A {// …
public:
A* Clone() const { // nonvirtual
A* p = DoClone();
assert( typeid(*p) == typeid(*this) && "DoClone incorrectly overridden" );
return p; // check DoClone's returned type
}
protected:
A( const A& );
virtual A* DoClone() const = 0;
};
class B : public A { // …
public:
virtual B* Clone() const {return new B(*this); }
protected:
B( const B& rhs ) : A( rhs ) {/* … */}
};
update
A bit of an explanation. The basic idea of the clone is the same as the other excellent answers here.
Now, with cloning you have the danger of slicing objects. For example, if some object which derives from A forgets to implement its own clone method, then a call to A* a = d->clone() will not return a full D object (assuming D is a descendant of A)
The NVI idiom says to separate a public interface from a virtual interface. Thus, in this example, clone is public, but not virtual. It call a protected virtual method, doClone, which does the actual cloning, and which derived objects also implement. Because of the split, the clone method can verify that the type of the cloned object matches the type of the original object.
I think you confuse classes with objects, i.e. instances of those classes.
Your container aclasses store pointers to existing objects. You may take the same pointer and push it several times in many different containers, this is not called cloning.

Qsharedpointer class

I am trying to use a smart pointer class in the following way
class A
{
friend class B;
virtual methods ();
protected:
virtual ~classA();
}
class B:public QSharedPointer<class A>
{
class B();
~ class B();
}
I plan to replace occurrences of Class A* with class B. Is this approach correct?
No this is not really the way to do this. It looks like your design goal here is to make it impossible for someone to allocate an object of type A without putting it in a smart pointer. The normal way to do this is not to inherit from the smart pointer, but to make your type have
A private constructor
A private destructor
A public static factory method returning in this case QSharedPointer
A private deleter class that is a friend of class A
Here is an example using boost::shared_ptr (I do not have a QT installation right now, but you should be able to just replace all instances of boost::shared_ptr with QSharedPointer)
#include <boost/shared_ptr.hpp>
class A {
private:
A() {}
~A() {}
struct deleter {
void operator()(A* val) {delete val;}
};
friend class deleter;
public:
static boost::shared_ptr<A> create() {
return boost::shared_ptr<A>(new A(), A::deleter());
}
};
int main()
{
//A a1; //compile error
//A *a2 = new A(); //compile error
boost::shared_ptr<A> a3 = A::create();
return 0;
}