Using "rule of zero" when I have pointers for polymorphism - c++

For the "rule of zero", I understand that I want to separate data management out into simple classes implementing rule of 3, rule of 5, whatever, so that the the more complicated classes can use constructors, assignment operators, etc, as automatically provided.
How does this work when a class member has to be a pointer because of polymorphism?
E.g., suppose I have a class
class MyClass{
private:
s_array<int> mynumbers;
s_array<double> mydoubles;
Base * object;
...
};
Here, Base is a base class with multiple derived classes, and object may be point to one of the derived classes. So object is a pointer in order to get polymorphism.
If it wasn't for the presence of this Base pointer, I could use the rule-of-zero for MyClass assuming s_array<> is properly implemented. Is there a way to set things up so that MyClass can use the rule of zero, even though object is a pointer? The behavior that I want on copy is that a new instance of MyClass gets a pointer to a new copy of object.

If you want to apply the rule of 0 with pointers, you need to use a shared pointer:
shared_ptr<Base> object;
However this doesn't fully fulfil your requirement. Because shared_ptr will provide for the rule of 5, but the copied pointers will always point to the same original object.
To get the behavior that you want, you'd need to create your own smart pointer that provides for the rule of 3 or 5.

If multiple MyClass objects can point to the same Base object, then simply use std::shared_ptr<Base> instead of Base* for your object member, as other responders mentioned.
But, if each MyClass object needs to point to its own Base object, then you have no choice but to implement the Rule of 3/5 in MyClass so that it can create its own Base object and/or clone a Base object from another MyClass object.

Just for the record, what I using to solve this is the following (basically as suggested as above):
template <class myClass>
class clone_ptr
{
public:
clone_ptr(){location=nullptr;}
clone_ptr(myClass* d) { location = d;}
~clone_ptr() { delete location; }
clone_ptr(const clone_ptr<myClass>& source){
if (source.location!=nullptr){
location=source.location->Clone();
}
else
location=nullptr;
}
clone_ptr& operator= (const clone_ptr<myClass>& source){
if (&source!=this){
if (source.location!=nullptr){
location=source.location->Clone();
}
else
location=nullptr;
}
return *this;
}
myClass* operator->() { return location; }
myClass& operator*() { return *location; }
private:
myClass* location;
};
I am implementing the Clone() function in the appropriate classes as follows:
class myClass : public parentClass{
...
public:
myClass* Clone()
{
return new myClass(*this);
}

Related

Auto-cloning unique_ptr

std::unique_ptr has a deleted copy constructor, which means that if you have a unique_ptr in your class Foo as a data member then you must write your own copy constructor for Foo and manually deep-copy that member (even if the compiler-generated copy constructor would be fine for all other members).
In order to be able to copy in a polymorphic way, the clone() method pattern can be used. Let's assume our objects have a clone method like this:
class Base {
virtual std::unique_ptr<Base> clone() = 0;
};
Foo looks like this now:
class Foo {
public:
...
Foo(Foo const& other)
: b(other.b->clone())
, // init 10 more members that could otherwise be auto-copied just fine
// with the automatically generated copy constructor
{}
...
private:
std::unique_ptr<Base> b;
//10 more data members
};
Now, I found a way to auto-clone Foo::b, by writing a wrapper over unique_ptr that defines the copy constructor and assignment by calling clone.
template <typename T>
class auto_cloned_unique_ptr
{
private:
std::unique_ptr<T> up;
public:
// copy constructor
auto_cloned_unique_ptr(auto_cloned_unique_ptr<T> const& other)
: up(other.up->clone()) {}
// copy assignment
auto_cloned_unique_ptr<T>& operator =(auto_cloned_unique_ptr<T> const& other)
{
this->up = other.up->clone();
return *this;
}
auto_cloned_unique_ptr(std::unique_ptr<T> _up)
: up(std::move(_up)) {}
// Delegate everything else to unique_ptr
auto_cloned_unique_ptr(auto_cloned_unique_ptr<T>&& other)
: up(std::move(other.up)) {}
auto_cloned_unique_ptr<T>& operator =(auto_cloned_unique_ptr<T>&& other)
{
this->up = std::move(other.up);
return *this;
}
auto operator *() const {return *up;}
auto operator->() const {return up.operator->();}
auto get() -> const {return up.get();}
};
Now if we use this we don't need to define our own copy constructor:
class Foo2 {
public:
...
private:
auto_cloned_unique_ptr<Base> b;
//10 more data members
};
Is such an approach very much frowned upon (for using a non-standard wrapper over unique_ptr)?
Let me first paraphrase what you want to do: You want that each instance of Foo has its own instance of Base in b; in particular, if you copy a Foo, the copy will have its own new Base, initially with the same "value". In other words, Base should behave like a value.
At the same time, you can't store Base directly in Foo because it is an abstract class. In other words, you want b to be polymorphic.
There you have it: you want a polymorphic value. Other people have recognized this need and proposed for C++20 as polymorphic_value<Base>. From the documentation:
The class template, polymorphic_value, confers value-like semantics on
a free-store allocated object. A polymorphic_value may hold an
object of a class publicly derived from T, and copying the
polymorphic_value will copy the object of the derived type.
It has a reference implementation that you can use as of now. Very simply put, it is an wrapper around std::unique_ptr similar to what you propose.
The problem with your approach is that it is changing the meaning of a unique_ptr. The key thing about a unique_ptr is that it tells who is the owner of an object. If you add a copy constructor for unique_ptr, what does that mean? Are you copying the ownership? A and B both uniquely own the thing? That does not make sense. If they share ownership, then you should be using the shared_ptr to indicate the shared ownership. If you want to have a unique owner of a copy of the object, you would naturally indicate that by make_unique(*pFoo). With base and derived objects, having the base object have a
virtual unique_ptr<Foo> Clone() const=0;
is a perfectly normal construct. That is, the derived classes know how to copy themselves so they don't produce a sliced copy, but they return a unique_ptr to the base class to indicate that you will own the copy they have produced. Within these clone operations, yes, you will need to explicitly handle non-copyable members of the derived classes, so you won't be able to just use a default or generated copy constructor. You need to answer "what does it mean to copy something that contains this thing that can't be copied?"
As a concrete example, what would it mean to copy a derived class that had a mutex? What if it were locked and another thread were waiting on it? See why it's hard to give a general answer?
This approach is fine, but you should be very carefull not to clone your objects when you did not intentd to.
Also inherriting from unique_ptr might improve performance

How to approach copying objects with smart pointers as class attributes?

From the boost library documentation I read this:
Conceptually, smart pointers are seen as owning the object pointed to,
and thus responsible for deletion of the object when it is no longer
needed.
I have a very simple problem: I want to use RAII for pointer attributes of a class that is Copyable and Assignable.
The copy and assignment operations should be deep: every object should have its own copy of the actual data. Also, RTTI needs to be available for the attributes (their type may also be determined at runtime).
Should I be searching for an implementation of a Copyable smart pointer (the data are small, so I don't need Copy on Write pointers), or do I delegate the copy operation to the copy constructors of my objects as shown in this answer?
Which smart pointer do I choose for simple RAII of a class that is copyable and assignable? (I'm thinking that the unique_ptr with delegated copy/assignment operations to the class copy constructor and assignment operator would make a proper choice, but I am not sure)
Here's a pseudocode for the problem using raw pointers, it's just a problem description, not a running C++ code:
// Operation interface
class ModelOperation
{
public:
virtual void operate = ();
};
// Implementation of an operation called Special
class SpecialModelOperation
:
public ModelOperation
{
private:
// Private attributes are present here in a real implementation.
public:
// Implement operation
void operate () {};
};
// All operations conform to ModelOperation interface
// These are possible operation names:
// class MoreSpecialOperation;
// class DifferentOperation;
// Concrete model with different operations
class MyModel
{
private:
ModelOperation* firstOperation_;
ModelOperation* secondOperation_;
public:
MyModel()
:
firstOperation_(0),
secondOperation_(0)
{
// Forgetting about run-time type definition from input files here.
firstOperation_ = new MoreSpecialOperation();
secondOperation_ = new DifferentOperation();
}
void operate()
{
firstOperation_->operate();
secondOperation_->operate();
}
~MyModel()
{
delete firstOperation_;
firstOperation_ = 0;
delete secondOperation_;
secondOperation_ = 0;
}
};
int main()
{
MyModel modelOne;
// Some internal scope
{
// I want modelTwo to have its own set of copied, not referenced
// operations, and at the same time I need RAII to for the operations,
// deleting them automatically as soon as it goes out of scope.
// This saves me from writing destructors for different concrete models.
MyModel modelTwo (modelOne);
}
return 0;
}
If you accept some requirements on your types, this can be done without requiring implementing virtual clone functions for all types. The particular requirements are that the types have accessible copy constructors, which some would deem undesirable because of potential for accidental slicing. Proper use of friending may mitigate the drawbacks of that, though.
If such is acceptable one can go about this by erasing the derived types under an interface that provides copy functionality:
template <typename Base>
struct clonable {
// virtual copy
// this clone function will be generated via templates
// no boilerplate is involved
virtual std::unique_ptr<clonable<Base>> clone() const = 0;
// expose the actual data
virtual Base* get() = 0;
virtual Base const* get() const = 0;
// virtual destructor
// note that this also obviates the need for a virtual destructor on Base
// I would probably still make it virtual, though, just in case
virtual ~clonable() = default;
};
This interface is implemented by a class templated on the most derived type, and thus knows how to make normal copies through the copy constructor.
template <typename Base, typename Derived>
struct clonable_holder : clonable<Base> {
// I suppose other constructors could be provided
// like a forwarding one for emplacing, but I am going for minimal here
clonable_holder(Derived value)
: storage(std::move(value)) {}
// here we know the most derived type, so we can use the copy constructor
// without risk of slicing
std::unique_ptr<clonable<Base>> clone() const override {
return std::unique_ptr<clonable<Base>>(new clonable_holder(storage));
}
Base* get() override { return &storage; }
Base const* get() const override { return &storage; }
private:
Derived storage;
};
This will generate virtual copy functions for us without extra boilerplate. Now we can build a smart pointer-like class on top of this (not quite a smart pointer because it does not give pointer semantics, but value semantics instead).
template <typename Base>
struct polymorphic_value {
// this constructor captures the most derived type and erases it
// this is a point where slicing may still occur
// so making it explicit may be desirable
// we could force constructions through a forwarding factory class for extra safety
template <typename Derived>
polymorphic_value(Derived value)
: handle(new clonable_holder<Base, Derived>(std::move(value))) {
static_assert(std::is_base_of<Base, Derived>::value,
"value must be derived from Base");
}
// moving is free thanks to unique_ptr
polymorphic_value(polymorphic_value&&) = default;
polymorphic_value& operator=(polymorphic_value&&) = default;
// copying uses our virtual interface
polymorphic_value(polymorphic_value const& that)
: handle(that.handle->clone()) {}
polymorphic_value& operator=(polymorphic_value const& that) {
handle = that.handle->clone();
return *this;
}
// other useful constructors involve upcasting and so on
// and then useful stuff for actually using the value
Base* operator->() { return handle.get(); }
Base const* operator->() const { return handle.get(); }
// ...
private:
std::unique_ptr<clonable<Base>> handle;
};
This is just a minimal interface, but it can easily be fleshed out from here to cover more usage scenarios.
It's a bit late, but for future viewers: There's a ready-to-use implementation in my header-only library Aurora and its SmartPtr tutorial. With Aurora, it's trivial to implement deep-copy through smart pointers. The following code works for any copyable type T:
aurora::CopiedPtr<T> first(new T);
aurora::CopiedPtr<T> second = first; // deep copy
This makes it often unnecessary to implement The Big Three/Five if your classes have pointer members.
It sounds like need to be able to make a smart pointer that creates a new copy of the object each time another smart pointer object is created. (Whether that copy is "deep" or not is up to the constructor of the object, I guess; the objects you're storing could have many levels deep of ownership, for all we know, so "deep" depends on the meaning of the objects. The main thing for our purposes is that you want something that creates a distinct object when the smart pointer is constructed with a reference from another one, rather than just taking out a pointer to the existing object.)
If I've understood the question correctly, then you will require a virtual clone method. There's no other way to call the derived class's constructor correctly.
struct Clonable {
virtual ~Clonable() {}
virtual Clonable* clone() = 0;
};
struct AutoPtrClonable {
AutoPtrClonable(Clonable* cl=0) : obj(cl) { }
AutoPtrClonable(const AutoPtrClonable& apc) : obj(apc.obj->clone()) { }
~AutoPtrClonable() { delete obj; }
// operator->, operator*, etc
Clonable* obj;
};
To use sample code, make it into a template, etc.
I've never heard about ready-to-use realisation, but you can simply do it by yourself.
First of all your should write some template wrapper class which has virtual clone method, returning copy of stored object. And then write some polymophic holder of that class which would be copyable
and don't forget about checked delete
http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Checked_delete
You have two solutions ( actually you have many more, but these make most sense to me :) ):
First, you can use std::unique_ptr. This is a good solution because it forces you to have one instance per pointer. (using std::shared_ptr instead would work as well, but if you do not add the code explicitely, copy and assignment for shared_ptr will "share" - especially what you want to avoid).
If you use std::unique_ptr, your copy constructor and assignment operator should explicitly deep-copy (using either a virtual clone method in the pointee's interface, or new operator in the call to the unique_ptr constructor).
Second, you can roll your own. There's nothing complicated about it, and we're talking about a small (10-20 lines or so) utility class.
Personally, if I had to use this smart pointer class in one place, I would use std::unique_ptr. Otherwise (multiple pointers, same behavior) I would roll my own, simply so I wouldn't have to repeat the deep copy for many instances (to keep with the DRY principle).

Using new operator for copy an object to heap without knowing its type

I have a doubt, the function below can receive an object of type A or something derived type.
A *copyToHeap(A &obj) {
A *ptr=new A(obj);
return ptr;
}
If we call it like this:
//B inherits from A
B bObj;
B *hPtr=copyToHeap(bObj);
The object pointed by hPtr is actually of type A or B?
Is safe doing this?
when you do the below in your code:
A* ptr = new A(obj);
you'll always get an A instance. obj will be treated as an A and a new A will get created based on the "A part" of obj.
The better approach is as an earlier reply indicated, add a virtual MakeCopy method to the base class and implement it for the derived classes.
virtual A* MakeCopy();
This method is implemented by making a copy of the object for which its called. It then gets implemented in the derived classes so if you have an A pointer which is actually a B object you'll get a true B copy and avoid the "slicing" which is occurring in your example.
The returned object is of type pointer to A, which means the object pointed to by hPtr is of type A. It's not safe since calling methods or members exclusive to B will cause a crash or undefined behavior. You're probably looking for the factory pattern.
A safe way is to provide a virtual clone method
#include <memory>
class Base
{
public:
virtual std::unique_ptr<Base> Clone() = 0;
};
class Derived : public Base
{
public:
Derived(int i) : i_(i)
{
}
std::unique_ptr<Base> Clone()
{
return std::unique_ptr<Derived>(new Derived(i_));
}
private:
int i_;
};
std::unique_ptr<Base> copyToHeap(std::unique_ptr<Base> obj)
{
return obj->Clone();
}
It is not safe, it is incorrect, and the compiler should give you some diagnostics. Did you try to compile with g++ -Wall if using GCC?
Doesn't compile:
B *hPtr=copyToHeap(bObj); //error: invalid conversion from ‘A*’ to ‘B*’
If you change the type of hPtr to A* it compiles, but you still get an A object. The default copy-constructor for A which you use will create an A object and copy the fields of the B object which were defined in A, slicing the B part off.
Because of all the problems described above/in this post -- if at all you can avoid it (and I can't think of a reason why you couldn't) -- you should not design your code to require "copyToHeap".
As Luchian points out, you probably want a factory. The factory creates your object on the heap to begin with (and returns a smart pointer to manage the lifetime of the object/pointer/memory).

Overriding operator new/delete in derived class

I have a stateless, abstract base class from which various concrete classes inherit. Some of these derived classes are stateless as well. Because many of them are created during a run, I'd like to save memory and overhead by having all stateless derived classes emulate a singleton, by overriding operator new()/delete(). A simplified example would look something like this:
#include <memory>
struct Base {
virtual ~Base() {}
protected:
Base() {} // prevent concrete Base objects
};
struct D1 : public Base { // stateful object--default behavior
int dummy;
};
struct D2 : public Base { // stateless object--don't allocate memory
void* operator new(size_t size)
{
static D2 d2;
return &d2;
}
void operator delete(void *p) {}
};
int main() {
Base* p1 = new D1();
Base* p2 = new D1();
Base* s1 = new D2();
Base* s2 = new D2();
delete p1;
delete p2;
delete s1;
delete s2;
return 0;
}
This example doesn't work: delete s2; fails because delete s1; called ~Base(), which deallocated the shared Base in d2. This can be addressed by adding the same trick with new/delete overloading to Base. But I'm not sure this is the cleanest solution, or even a correct one (valgrind doesn't complain, FWIW). I'd appreciate advice or critique.
edit: actually, the situation is worse. The Base class in this example isn't abstract, as I claimed. If it's made abstract, through the addition of a pure virtual method, then I can no longer apply the new/delete overriding trick, because I cannot have a static variable of type Base. So I don't have any solution for this problem!
You just can't do that - that would violate "object identity" requirement that states that each object must have its own address. You have to allocate distinct memory block to each object - this can be done rather fast if you override operator new to use a fast block allocator specifically tailored for objects of fixed size.
I would say the best solution here is to make your derived class an actual singleton. Make your derived constructor private and just provide a static Base* getInstance() method that either creates the required object or returns the static instance. This way the only way to get a D1 object would be via this method since calling new D1 would be illegal.

What's the best signature for clone() in C++?

As Scott Myers wrote, you can take advantage of a relaxation in C++'s type-system to declare clone() to return a pointer to the actual type being declared:
class Base
{
virtual Base* clone() const = 0;
};
class Derived : public Base
{
virtual Derived* clone() const
};
The compiler detects that clone() returns an pointer to the type of the object, and allows Derived to override it to return a pointer to derived.
It would desirable to have clone() return a smart pointer that implies transfer of ownership semantics, like the following:
class Base
{
virtual std::auto_ptr<Base> clone() const = 0;
};
class Derived : public Base
{
virtual std::auto_ptr<Derived> clone() const;
};
Unfortunately, the relaxation of the conventions does not apply to templated smart pointers, and the compiler will not allow the override.
So, it seems I am left with two options:
Have clone() return a "dumb" pointer, and document that clients are responsible for disposing of it.
Have clone() return a smart base pointer, and have clients use dynamic_cast to save them to a Derived pointer if they need it.
Is one of these approaches preferred? Or is there a way for me to eat my transfer of ownership semantics and have my strong type safety too?
Use the Public non-virtual / Private virtual pattern :
class Base {
public:
std::auto_ptr<Base> clone () { return doClone(); }
private:
virtual Base* doClone() { return new (*this); }
};
class Derived : public Base {
public:
std::auto_ptr<Derived> clone () { return doClone(); }
private:
virtual Derived* doClone() { return new (*this); }
};
The syntax isn't quite as nice, but if you add this to your code above, doesn't it solve all your problems?
template <typename T>
std::auto_ptr<T> clone(T const* t)
{
return t->clone();
}
I think the function semantics are so clear in this case that there is little space for confusion. So I think you can use the covariant version (the one returning a dumb pointer to the real type) with an easy conscience, and your callers will know that they are getting a new object whose property is transferred to them.
It depends on your use case. If you ever think you will need to call clone on a derived object whose dynamic type you know (remember, the whole point of clone is to allow copying without knowing the dynamic type), then you should probably return a dumb pointer and load that into a smart pointer in the calling code. If not, then you only need to return a smart_ptr and so you can feel free to return it in all overrides.
Tr1::shared_ptr<> can be casted like it were a raw pointer.
I think have clone() return a shared_ptr<Base> pointer is a pretty clean solution. You can cast the pointer to shared_ptr<Derived> by means of tr1::static_pointer_cast<Derived> or tr1::dynamic_pointer_cast<Derived> in case it is not possible to determine the kind of cloned object at compile time.
To ensure the kind of object is predictible you can use a polymorphic cast for shared_ptr like this one:
template <typename R, typename T>
inline std::tr1::shared_ptr<R> polymorphic_pointer_downcast(T &p)
{
assert( std::tr1::dynamic_pointer_cast<R>(p) );
return std::tr1::static_pointer_cast<R>(p);
}
The overhead added by the assert will be thrown away in the release version.
That's one reason to use boost::intrusive_ptr instead of shared_ptr or auto/unique_ptr. The raw pointer contains the reference count and can be used more seamlessly in situations like this.
Updating MSalters answer for C++14:
#include <memory>
class Base
{
public:
std::unique_ptr<Base> clone() const
{
return do_clone();
}
private:
virtual std::unique_ptr<Base> do_clone() const
{
return std::make_unique<Base>(*this);
}
};
class Derived : public Base
{
private:
virtual std::unique_ptr<Base> do_clone() const override
{
return std::make_unique<Derived>(*this);
}
}
You could have two methods, a virtual clone() that returns a smart pointer wrapper around the base type, and a non-virtual clone2() that returns the correct type of smart pointer.
clone2 would obviously be implemented in terms of clone and encapsulate the cast.
That way can get the most derived smart pointer that you know at compile time. It may not be the most derived type overall, but it uses all the information available to the compiler.
Another option would be to create a template version of clone that accepts the type you are expecting, but that adds more burden on the caller.