In the following example we have a class Class that contains a Bridge object that takes care of all the memory handling for us (rule of three).
class Base {
public:
Base() {};
virtual Base* clone() const = 0;
virtual ~Base() {};
};
class Derived : public Base {
public:
Derived() {};
virtual Base* clone() const {
return new Derived(*this);
}
virtual ~Derived() {}
};
class Bridge {
public:
Bridge(const Bridge& bridge_) {
base = bridge_.base->clone();
}
Bridge(const Base& base_) {
base = base_.clone();
}
~Bridge() { delete base; }
Bridge& operator=(const Bridge& assignFrom) {
if(this != &assignFrom) {
delete base;
base = assignFrom.base->clone();
}
return *this;
}
private:
Base *base;
};
class Class {
public:
Class(const Bridge& bridge_) : bridge(bridge_) {};
private:
Bridge bridge;
};
int main()
{
Derived derived;
Class c(derived);
Class c1(c);
}
Now, I have just learned about smart pointers and was trying to recreate the above example using unique_ptr. To my understanding, we basically don't need to implement the rule of 3 ourselves as the smart pointer contains it already. To test this, I made the following example:
class BaseSMRT {
public:
BaseSMRT() {};
virtual std::unique_ptr<BaseSMRT> clone() const = 0;
virtual ~BaseSMRT() {};
};
class DerivedSMRT : public BaseSMRT {
public:
DerivedSMRT() {};
virtual std::unique_ptr<BaseSMRT> clone() const {
return std::make_unique<DerivedSMRT>(*this);
}
virtual ~DerivedSMRT() {}
};
class ClassSMRT {
public:
ClassSMRT(const BaseSMRT& base) {
ptr = base.clone();
};
private:
std::unique_ptr<BaseSMRT> ptr;
};
int main()
{
DerivedSMRT derivedSMRT;
ClassSMRT cSMRT(derivedSMRT);
ClassSMRT cSMRT2(cSMRT); // error: Call to implicitly-deleted copy constructor of 'ClassSMRT'
}
As you can see in the above example, initialising cSMRT2 with cSMRT through the copy constructor doesn't work and gives me the above error.
I don't get this: Why is it that I can call Class's default copy constructor like this, Class c1(c);, but not call ClassSMRT's default copy constructor, ClassSMRT cSMRT2(cSMRT);?
This suggests that the rule of three isn't already implemented for us when we are using unique_ptr.
unique_ptr is designed to stop accidental copies. You want to implicitly clone you polymorphic type when copied. unique_ptr doesn't (directly) fit your uses.
I would suggest a rename of Bridge
template </*Cloneable*/ typename T>
class clone_ptr {
public:
clone_ptr(const T& base_)
: base(base_.clone()) {}
clone_ptr(const clone_ptr& other)
: base(other.base->clone()) {}
clone_ptr(clone_ptr&& other) = default;
clone_ptr& operator=(clone_ptr other) {
base = std::move(other.base);
return *this;
}
private:
std::unique_ptr<T> base;
};
Related
I am using a composite design pattern and I want to clone my objects from my composite class. I tried to make a generic clone method in my component class, but when I try to send the concrete type of my object to the generic (template) method, 'typeof' and 'typeid' returns the abstract class type. So, when I try to use new typeof(object), I see the error
"invalid new-expression of abstract class type 'Component'".
My compiler is MigGW 32 bits.
As I can't know the type of my object, I can't use dynamic_cast.
Am I using typeof/typeid wrongly or should I use other keyword to know the concrete object type?
#include <iostream>
#include <vector>
#include <typeinfo>
class Component
{
public:
template <typename Tdest> typename std::remove_cv<typename std::remove_pointer<Tdest>::type>::type* clone() const
{
typedef typename std::remove_cv<typename std::remove_pointer<Tdest>::type>::type NO_POINTER_NOR_CV;
return new typeof(NO_POINTER_NOR_CV)(*dynamic_cast<const NO_POINTER_NOR_CV*>(this));
}
virtual void manipulateComponents() = 0;
virtual void add(Component* comp) = 0;
protected:
std::vector<const Component*> _v;
};
class Leaf : public Component
{
void manipulateComponents() override { return; }
void add(Component* comp) override { return; }
};
class Composite : public Component
{
public:
void manipulateComponents() override
{
for(auto component : _v)
{
std::cout << typeid(component).name() << std::endl; // print PK9Component
component->clone<typeof(component)>();
/* ... */
}
}
void add(Component* comp) override { _v.push_back(comp); }
};
int main(int argc, char* argv[])
{
Component* l = new Leaf();
Component* c = new Composite();
Component* parent = new Composite();
parent->add(l);
parent->add(c);
parent->manipulateComponents();
}
You are not getting the details of the derived type using typeid since you are using it on a pointer. Dereference the pionter in the call to get the name of the derived type.
Change
std::cout << typeid(component).name() << std::endl; // print PK9Component
// PK9Component seems indicate that it is a pointer to a Component.
to
std::cout << typeid(*component).name() << std::endl;
// ^^
If you want a clone method, you have to add a virtual function to return it, as in:
struct A
{
virtual std::unique_ptr<A> clone() const = 0;
A() = default;
A(A const&) = default;
A(A&&) = default;
A& operator=(A&&) = default;
A& operator=(A const&) = default;
virtual ~A() = default;
};
struct B : A
{
std::unique_ptr<A> clone() const override
{
assert(typeid(*this) == typeid(B));
return std::make_unique<B>(*this);
}
};
The assert protects (at run time) against deriving from B w/o overriding the clone() method.
The C++ Committee is working on A polymorphic value-type for C++, but that won't be available for a while.
No amount of typeof magic in your clone method will give you the type of a subclass of a non-templated class. It can give you the type of an instantiated template, but the only possible instantiation of your clone method here is in your base class. Subclassing doesn't redefine template methods.
If you really want to, you can use template methods in subclassing if you're willing to use the "Curiously Recurring Template Pattern". There's a sample clone implementation on Wikipedia, which I'll quote here:
// Base class has a pure virtual function for cloning
class Shape {
public:
virtual ~Shape() {};
virtual Shape *clone() const = 0;
};
// This CRTP class implements clone() for Derived
template <typename Derived>
class Shape_CRTP : public Shape {
public:
virtual Shape *clone() const {
return new Derived(static_cast<Derived const&>(*this));
}
};
// Nice macro which ensures correct CRTP usage
#define Derive_Shape_CRTP(Type) class Type: public Shape_CRTP<Type>
// Every derived class inherits from Shape_CRTP instead of Shape
Derive_Shape_CRTP(Square) {};
Derive_Shape_CRTP(Circle) {};
With CRTP, you may do:
template <typename Derived>
class IClonable
{
public:
virtual ~IClonable() = default;
std::unique_ptr<Derived> clone() const {
return std::unique_ptr<Derived>(cloneImpl());
}
protected:
virtual Derived* cloneImpl() const = 0;
};
template <typename Derived, typename Base>
class Clonable : public Base
{
public:
std::unique_ptr<Derived> clone() const { // Hide Base::clone to return static type.
return std::unique_ptr<Derived>(static_cast<Derived*>(cloneImpl()));
}
protected:
Clonable* cloneImpl() const { return new Derived{static_cast<const Derived&>(*this)}; }
};
And then:
class Component : public IClonable<Component>
{
public:
virtual void manipulateComponents() = 0;
virtual void add(const Component&) = 0;
};
class Leaf : public Clonable<Leaf, Component>
{
public:
void manipulateComponents() override {}
void add(const Component&) override {}
};
class Composite : public Clonable<Composite, Component>
{
public:
void manipulateComponents() override
{
for (const auto* component : _v)
{
auto cloned = component->clone(); // std::unique_ptr<Component>
/* ... */
}
}
void add(const Component& comp) override { _v.push_back(&comp); }
protected:
std::vector<const Component*> _v;
};
With possible usage:
Leaf l;
Composite c;
auto parent = c.clone(); // std::unique_ptr<Composite>
parent->add(l);
parent->add(c);
parent->manipulateComponents();
I'm an C++ beginner, please help me.
I can't use template class as the constructor' s parameter.
xcode shows 'No matching constructor for initialization of 'Work'' error.
The whole source code below, any one can fix this?
#include <iostream>
class Base {
public:
virtual void hello_world() const {
printf("Base::hello_world()\n");
};
};
class Derived : public Base {
public:
void hello_world() const {
printf("Derived::hello_world()\n");
};
};
template<class T>
class Templ {
public:
Templ(const T &t) : _value(t) {}
const T& getValue() const{
return _value;
}
private:
const T &_value;
};
class Work {
public:
Work(const Templ<Base*> &base) : mBase(base) {}
void working() {
mBase.getValue()->hello_world();
}
private:
const Templ<Base*> &mBase;
};
int main(int argc, const char * argv[]) {
Templ<Base*> base(new Base());
//OK
Work w_base(base);
Templ<Derived*> derived(new Derived());
//error: No matching constructor for initialization of 'Work'
Work w_derived(derived);
return 0;
}
Work w_derived(derived); is never going to work as Work expects a Templ<Base*>. A Templ<Base*> and a Templ<Derived*> are two different, distinct types. Just a like a std::vector<int> is not the same as a std::vector<std::complex>.
What you can do though is create a Templ<Base*> from a pointer to a Dervied and then create a Work with that. Something like
Templ<Base*> derived(new Derived());
Work w_derived(derived);
Live Example
Also as pointed out in the comments since you are using polymorphism you need to have a virtual destructor in the base class. If the destructor is not virtual then only the base class destructor will run and you will your object will not be properly destructed.
In C++, this would look like this
struct Base
{
virtual ~Base() {} // enable descruction of base through pointer to Base
virtual void hello_world() const
{ std::cout<<"Base::hello_world()\n"; }
};
struct Derived : Base
{
void hello_world() const override
{ std::cout<<"Derived::hello_world()\n"; }
};
struct work
{
work(const Base*p)
: ptr(p) {}
void working() const
{ ptr->hello_world(); }
private:
std::unique_ptr<const Base> ptr;
};
int main()
{
Work w_base(new Base);
Work w_derived(new Derived);
w_base.working();
w_derived.working();
}
Note the following
the virtual destructor of Base ensures that a derived class is properly destructed from a pointer to Base, so that std::unique_ptr<> works correctly.
the override keyword ensures that we actually implement a virtual method.
the usage of std::unique_ptr<> avoids the Templ class. Morever, its destructor will automatically and correctly destroy the pointed-to object, avoiding the memory leak of your code.
return 0 is not required for int main(), but automatically generated.
Here is the problem:
I have a class called Object, whose constructor accepts a std::function like this:
#include <functional>
#include <iostream>
#include <memory>
#include <string>
class Object {
public:
Object(std::function<void(int param)> f) : func(f) {}
~Object() { func(0); }
private:
std::function<void(int param)> func;
};
Then an abstract base class and several derived classes like this:
class AbstractBase {
public:
AbstractBase() {
// How to initialize object.
}
virtual std::string toString() const = 0;
private:
Object object;
};
class Derived1 : public AbstractBase {
public:
std::string toString() const override { return "Derived1"; }
}
class Derived2 : public AbstractBase {
public:
std::string toString() const override { return "Derived2"; }
}
I am trying to initialize the object in AbstractBase like this:
AbstractBase()
: object([this](int param) {
// do something
std::cout << toString() << std::endl;
// do something
}) {}
It compiles successfully, but raises "pure virtual method called" when AbstractBase is deleted. So how can I initialize object in the AbstractBase and make sure toString from derived class is called in the std::function?
The problem here is order of destructors calls.
Here is a simple example:
#include <functional>
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class Object {
public:
Object(){ cout<<"O\n"; }
~Object() { cout<<"~O\n"; }
};
class AbstractBase {
public:
AbstractBase(){ cout<<"A\n"; }
~AbstractBase() { cout<<"~A\n"; }
private:
Object object;
};
class Derived1 : public AbstractBase {
public:
Derived1() : AbstractBase()
{ cout<<"1\n"; }
~Derived1() { cout<<"~1\n"; }
};
class Derived2 : public AbstractBase {
public:
Derived2() : AbstractBase()
{ cout<<"2\n"; }
~Derived2() { cout<<"~2\n"; }
};
int main() {
Derived1 d1;
Derived2 d2;
return 0;
}
And the output:
O
A
1
O
A
2
~2
~A
~O
~1
~A
~O
As you can see Objects destructors are called after Derived* destructors, so, in your code, Object is trying to call already destructed Derived* method.
The C++ standard forbids calling a pure virtual method from either a constructor or a destructor.
If you were to directly call toString() from ~AbstractBase() you would almost certainly get a compiler error.
Your use of a lambda is basically "sneaking" the disallowed behaviour past the compiler.
Instead, you need to move the responsibility up to Derived - consider something like this:
struct Object {
Object(decltype(func) f) : func(f) {};
~Object() { func(); }
private:
std::function<void()> func; //removed param since it's unused in your example
};
struct AbstractBase {
A() = delete;
protected:
A(Object&& o) : obj(o) {} //we'll be using an rvalue in this example, be mindful of object lifetime in other usages
private:
Object& o;
};
struct Derived : AbstractBase {
Derived() : AbstractBase(Object{[this]() { writestr(); }}) {}
private:
void writestr() { std::cout << "yes"; }
};
int main() {
Derived d;
return 0;
}
Consider the following code:
class Base
{
public:
virtual void* allocate(){ return nullptr; }
};
template <class T> class BaseTemplate : public Base
{
public:
void* allocate() override { return new T(); }
};
class IntSpecialization : public BaseTemplate<int>
{
};
Base GetSpecialization(const int&){ return IntSpecialization(); }
The goal is to be able to use template to implement specializations, but still allow users to work using the base class interface, such as:
int a;
auto s = GetSpecialization(a);
auto p = s.allocate();
The above code does not work; s.allocate() always return nullptr for obvious reasons.
I absolutely need the GetSpecialization function to return the Base non-template class, so how do I go about this?
The Base class virtual method cannot be pure, because otherwise it becomes abstract and it will fail the compilation at GetSpecialization.
What is the best approach to solve this pattern? Using C++11?
Thanks!
Base GetSpecialization(const int&){ return IntSpecialization(); }
You're slicing the IntSpecialization object above. To make your code work, GetSpecialization must return a Base *, or a Base&. For instance, the following will work as you intended it to:
std::unique_ptr<Base> GetSpecialization(const int&)
{
return std::unique_ptr<Base>(new IntSpecialization());
}
Live demo
For the above code to work, you'll need to add a virtual destructor to Base.
class Base
{
public:
virtual void* allocate(){ return nullptr; }
virtual ~Base() = default;
};
Otherwise, when the unique_ptr goes out of scope it'll call delete ptr;, where the type of ptr is Base *, and polymorphic deletion of a derived class object through a base class pointer is undefined behavior unless the base class destructor is virtual.
Just make Base have pointer to BaseTemplate:
class BaseInterface {
public:
virtual void* allocate() = 0;
}
class Base
{
std::unique_ptr<BaseInterface> interface;
public:
Base( BaseInterface *i ) : interface( i ) {}
void* allocate(){ return interface->allocate(); }
};
template <class T> class BaseTemplate : public BaseInterface
{
public:
void* allocate() override { return new T(); }
};
class IntSpecialization : public BaseTemplate<int>
{
};
Base GetSpecialization(const int&){ return Base( new IntSpecialization ); }
Less verbose solution is to use std::function and lambda
class Base
{
public:
typedef std::function<void *()> creator;
Base( const creator &c ) : cr( c ) {}
void *allocate() { return cr(); }
private:
creator cr;
};
template<class T>
Base GetSpecialization( const T & ) { return Base( []() { return new T; } ); }
I have a hierarchie of classes that implement the Prototype pattern and I would like to use move semantics to limit objects deep copy. I tried to adapted the pattern with a move() member function which meaning is that I do not need the original object anymore. Here is what I have so far:
#include <iostream>
#include <utility>
#include <vector>
struct base
{
virtual ~base() { }
virtual base* clone() const = 0;
virtual base* move() = 0;
};
struct derived1 : public base
{
derived1() { std::cout << "derived1::derived1()\n"; }
derived1(const derived1&) { std::cout << "derived1::derived1(const derived1&)\n"; }
derived1(derived1&&) { std::cout << "derived1::derived1(derived1&&)\n"; }
virtual ~derived1() { }
virtual base* clone() const { return new derived1(*this); }
virtual base* move() { return new derived1(std::move(*this)); }
};
struct derived2 : public base
{
derived2() { std::cout << "derived2::derived2()\n"; }
derived2(const derived2&) { std::cout << "derived2::derived2(const derived2&)\n"; }
derived2(derived2&&) { std::cout << "derived2::derived2(derived2&&)\n"; }
virtual ~derived2() { }
virtual base* clone() const { return new derived2(*this); }
virtual base* move() { return new derived2(std::move(*this)); }
};
std::vector<base*> vec;
void foo(const base& obj)
{
vec.push_back(obj.clone());
}
void foo(base&& obj)
{
vec.push_back(obj.move());
}
int main()
{
derived1 d1;
derived2 d2;
foo(d1);
foo(d2);
foo(derived1());
foo(derived2());
}
When I run it, it show that the good constructors are used:
derived1::derived1()
derived2::derived2()
derived1::derived1(const derived1&)
derived2::derived2(const derived2&)
derived1::derived1()
derived1::derived1(derived1&&)
derived2::derived2()
derived2::derived2(derived2&&)
So far, it seems good. I am just not sure if this is a standard compliant usage of the rvalue references. Is there a point I did not think of that would produce undesirable results?
For recurring method definition I prefer CRTP. For your case I'd declare something like:
template<typename TDerived>
class virtually_clonable : public base
{
public:
virtual base* clone() override
{
return new TDerived(*AsDerived());
}
virtual base* move() override
{
return new TDerived(std::move(*AsDerived()));
}
private:
TDerived* AsDerived()
{
return static_cast<TDerived*>(this);
}
};
And while implementing the classes:
class derived1 : public virtually_clonable<derived1>
{
public:
/* your ctors goes here*/
/* no need to implement clone/move again */
};
class derived2 : public virtually_clonable<derived2>
{
public:
/* your ctors goes here*/
/* no need to implement clone/move again */
};
By the way you may want to return shared_ptr objects instead of raw pointers. That is usually the case for clonable types instead of unique_ptr.