Copy object - keep polymorphism - c++

The following code tries to copy an object and keep the original type.
Unfortunately it does not work (every copied object will become a Super instead of being of the same class as its original).
Please note that copySuper(const Super& givenSuper) should not know anything about the subclasses of Super.
Is it possible to do such a copy? Or do I have to change the definition of copySuper ?
#include <string>
#include <iostream>
class Super
{
public:
Super() {};
virtual ~Super() {};
virtual std::string toString() const
{
return "I'm Super!";
}
};
class Special : public Super
{
public:
Special() {};
virtual ~Special() {};
virtual std::string toString() const
{
return "I'm Special!";
}
};
Super* copySuper(const Super& givenSuper)
{
Super* superCopy( new Super(givenSuper) );
return superCopy;
}
int main()
{
Special special;
std::cout << special.toString() << std::endl;
std::cout << "---" << std::endl;
Super* specialCopy = copySuper(special);
std::cout << specialCopy->toString() << std::endl;
return 0;
}
//Desired Output:
// # I'm Special!
// # ---
// # I'm Special!
//
//Actual Output:
// # I'm Sepcial!
// # ---
// # I'm Super!

Try this:
class Super
{
public:
Super();// regular ctor
Super(const Super& _rhs); // copy constructor
virtual Super* clone() const {return(new Super(*this));};
}; // eo class Super
class Special : public Super
{
public:
Special() : Super() {};
Special(const Special& _rhs) : Super(_rhs){};
virtual Special* clone() const {return(new Special(*this));};
}; // eo class Special
Note that we have implemented a clone() function that Special (and any other derivative of Super) overrides to create the correct copy.
e.g:
Super* s = new Super();
Super* s2 = s->clone(); // copy of s
Special* a = new Special();
Special* b = a->clone(); // copy of a
EDIT: As other commentator pointed out, *this, not this. That'll teach me to type quickly.
EDIT2: Another correction.
EDIT3: I really should not post so quickly when in the middle of work. Modified return-type of Special::clone() for covariant return-types.

This is what you need :
class Super
{
public:
Super()
{
}
virtual Super* clone() const
{
return( new Super(*this) );
};
};
class Special : public Super
{
public:
Special() : Super()
{
};
Special(const Special& _rhs) : Super(_rhs)
{
};
virtual Special* clone() const
{
return( new Special( *this ) );
};
};
int main()
{
Special a;
Super &c( a );
Super *b1 = c.clone();
Special *b2 = a.clone();
Super *b3 = a.clone();
}
One of previous examples has the clone for derived class wrong. The above is correct way of implementing the clone method.

What you want is generally implemented using an abstract clone method in the base class. Special will typically implement this method by returning new Special(*this).
Also note that it is considered a best practice to make base classes uncopyable.

Just for the record, this is in the C++ FAQ:
http://www.dietmar-kuehl.de/mirror/c++-faq/abcs.html#faq-22.5

Related

How to deal with different classes which have the same method?

For example, I have 2 classes (in reality, it's more, that's why I'm asking this question) with the same methods:
class class1{
public:
void init(){
//something
}
void dostuff(){
//something
}
//
};
class class2{
public:
void init(){
//something
}
void dostuff(){
//something
}
//
};
And now a third one in which I want to deal with the two classes in the same manner:
class upclass{
public:
upclass(class12* argclass){
myclass=argclass;
myclass->init();
}
void domorestuff(){
myclass->dostuff();
}
private:
class12* myclass; //pointer to class 1 OR class 2
};
My question is now, do I need multiple constructors and multiple declarations to make it work or is there a way around it? Is it even possible to make "class12" a spacekeeper for these types without preprocessor-directives?
I am sorry to say, this is a wide field and there are really many many possible solution.
But I guess that we are talking about object- oriented programming, derivation and plymorphic functions. What you describe, will be typically solved with a class hierachy.
You have one base class with virtual (polymorphic) functions.
Then you derive other classes from this base class and override the virtual functions from the base class.
In a 3rd step, you create some instances of the derived classes dynamically, during runtime and you store the newly created classes (their address) in a pointer to the base class.
Later, you can call any of the virtual overriden function through the base class pointer. And mechanism behind the scenes will call the correct function for you.
Additionally. You defined some function init. Such a function name suggests the usage of a class-constructor. This will be called automatically in the correct sequence. First the base class constructor and then the derived class constructor.
Please see the below example:
#include <iostream>
#include <string>
class Base {
std::string baseName{};
public:
Base() { // Do initialization stuff
baseName = "Base";
std::cout << "\nConstructor Base\n";
}
virtual void doStuff() { // virtual function
std::cout << baseName << '\n';
}
};
class Derived1 : public Base {
std::string derivedName{};
public:
Derived1() : Base() { // Do initialization stuff
derivedName = "Derived1";
std::cout << "Constructor Derived1\n";
}
void doStuff() override { // Override virtaul function
std::cout << derivedName << '\n';
}
};
class Derived2 : public Base {
std::string derivedName{};
public:
Derived2() : Base() { // Do initialization stuff
derivedName = "Derived2";
std::cout << "Constructor Derived2\n\n";
}
void doStuff() override { // Override virtaul function
std::cout << derivedName << '\n';
}
};
int main() {
Base* base = new Base();
Base* derived1 = new Derived1(); // Store in base class pointer
Base* derived2 = new Derived2(); // Store in base class pointer
base->doStuff();
derived1->doStuff(); // Magic of polymorphism
derived2->doStuff(); // Magic of polymorphism
}
The Base class pointer will accept all classes derived from Base.
Please note. In reality you ould not use raw pointers and also to the constructor differently. This is just fotr demo.
But, you need to read several books about it to get the complete understanding.
You can explicitly write "store one of these" via std::variant and obtain the actual type (when needed) through std::visit:
#include <variant>
using class12 = std::variant<class1*, class2*>;
class upclass {
public:
upclass(class12 argclass): myclass{argclass} {
visit([](auto classn) { classn->init(); }, myclass);
}
void domorestuff() {
visit([](auto classn) { classn->dostuff(); }, myclass);
}
private:
class12 myclass;
};
If those visits get too repetitive, you might consider writing a pretty API to hide them:
class prettyclass12: public std::variant<class1*, class2*> {
private: // both g++ and clang want variant_size<>, a quick hack:
auto& upcast() { return static_cast<std::variant<class1*, class2*>&>(*this); }
public:
using std::variant<class1*, class2*>::variant;
void init() { visit([](auto classn) { classn->init(); }, upcast()); }
void dostuff() { visit([](auto classn) { classn->dostuff(); }, upcast()); }
};
class prettyupclass {
public:
prettyupclass(prettyclass12 argclass): myclass{argclass} { myclass.init(); }
void domorestuff() { myclass.dostuff(); }
private:
prettyclass12 myclass;
};

Can I define a virtual function (or similar) to return of vector of derived class members?

I have a base class B with derived classes X, Y and Z (in fact, more than 20 derived classes). Each class has a tag() function that identifies which (derived) class it is. My program stores instances of the derived classes as pointers in a vector defined as vector<B*>. Each derived class may appear in this vector 0..n times.
I would like to have a function that looks through the vector for instances of a derived type and returns a new vector with the type of the derived class, eg
#include <vector>
using namespace std;
class B {
public:
// ...
virtual int tag() {return 0xFF;};
};
class X : public B {
// ...
int tag() {return 1;};
vector<X*> find_derived(vector<B*> base_vec) {
vector<X*> derived_vec;
for (auto p : base_vec) {
if (p->tag() == tag()) {
derived_vec.push_back((X*) p);
}
}
return derived_vec;
}
};
Obviously I don't want to have to define find_derived in each derived class but I don't see how to do this as a virtual function. Currently I am doing it using a macro but, since I am learning C++, I woudl prefer a method that used language constructs rather than those in the pre-processor. Is there another way?
One possibility:
template <typename D>
class FindDerivedMixin {
public:
vector<D*> find_derived(const vector<B*>& base_vec) {
int my_tag = static_cast<D*>(this)->tag();
vector<D*> derived_vec;
for (auto p : base_vec) {
if (p->tag() == my_tag) derived_vec.push_back(static_cast<D*>(p));
}
return derived_vec;
}
};
class X : public B, public FindDerivedMixin<X> {};
Like the previous answer, what you need is some template programming.
This is an example without mixin though:
#include <vector>
#include <iostream>
#include <type_traits>
#include <string>
//-----------------------------------------------------------------------------
// Base class
class Base
{
public:
virtual ~Base() = default;
// pure virtual method to be implemented by derived classes
virtual void Hello() const = 0;
protected:
// example of a constuctor with parameters
// it is protected since no instances of Base
// should be made by accident.
explicit Base(const std::string& message) :
m_message(message)
{
}
// getter for private member variable
const std::string& message() const
{
return m_message;
}
private:
std::string m_message;
};
//-----------------------------------------------------------------------------
// Class which contains a collection of derived classes of base
class Collection
{
public:
Collection() = default;
virtual ~Collection() = default;
// Add derived classes to the collection.
// Forward any arguments to the constructor of the derived class
template<typename type_t, typename... args_t>
void Add(args_t&&... args)
{
// compile time check if user adds a class that's derived from base.
static_assert(std::is_base_of_v<Base, type_t>,"You must add a class derived from Base");
// for polymorphism to work (casting) we need pointers to derived classes.
// use unique pointers to ensure it is the collection that will be the owner of the
// instances
m_collection.push_back(std::make_unique<type_t>(std::forward<args_t>(args)...));
}
// Getter function to get derived objects of type_t
template<typename type_t>
std::vector<type_t*> get_objects()
{
static_assert(std::is_base_of_v<Base, type_t>, "You must add a class derived from Base");
// return non-owning pointers to the derived classes
std::vector<type_t*> retval;
// loop over all objects in the collection of type std::unique_ptr<Base>
for (auto& ptr : m_collection)
{
// try to cast to a pointer to derived class of type_t
type_t* derived_ptr = dynamic_cast<type_t*>(ptr.get());
// if cast was succesful we have a pointer to the derived type
if (derived_ptr != nullptr)
{
// add the non-owning pointer to the vector that's going to be returned
retval.push_back(derived_ptr);
}
}
return retval;
}
private:
std::vector<std::unique_ptr<Base>> m_collection;
};
//-----------------------------------------------------------------------------
// some derived classes for testing.
class Derived1 :
public Base
{
public:
explicit Derived1(const std::string& message) :
Base(message)
{
}
virtual ~Derived1() = default;
void Hello() const override
{
std::cout << "Derived1 : " << message() << "\n";
}
};
//-----------------------------------------------------------------------------
class Derived2 :
public Base
{
public:
explicit Derived2(const std::string& message) :
Base(message)
{
}
virtual ~Derived2() = default;
void Hello() const override
{
std::cout << "Derived2 : " << message() << "\n";
}
};
//-----------------------------------------------------------------------------
int main()
{
Collection collection;
collection.Add<Derived1>("Instance 1");
collection.Add<Derived1>("Instance 2");
collection.Add<Derived2>("Instance 1");
collection.Add<Derived2>("Instance 2");
collection.Add<Derived1>("Instance 3");
// This is where template programming really helps
// the lines above where just to get the collection filled
auto objects = collection.get_objects<Derived1>();
for (auto& derived : objects)
{
derived->Hello();
}
return 0;
}

C++ private polymorphic implementation design

This is a C++(11) question.
I have a object Obj myObj encapsulating an object f of type MyType.
Depending on runtime context, the object fshould behave differently.
One natural way of implementing this would be for the class Obj to encapsulate a pointer to an abstract base class MyType, which would, depending on the context point to different (public) child of MyType, such as MyType1, MyType2, etc.
However, I'm not very keen on Obj "suffering" the consequences of MyType being polymorphic, i.e. having to deal with a pointer. In particular, if I make it a std::unique_ptr<MyType>, it implies that Obj can either not be copied or that one needs to give it a proper copy constructor that deals with copying MyType ressources.
In my opinion, MyType being polymorphic shouldn't be Obj's problem.
I came with the following classes. Essentially the idea is to hide the pointer within MyTypeprivate attributes. In addition my second question concerns the fact that concrete implementations of MyTypeImpl may share some code shouldn't be repeated. I've put that in a class from which concrete implementations privately inherit.
I'm curious what more expert developers than me would think about it. Is it too heavy "just to hide the pointer"? Is there a better way to do it?
#include <iostream>
#include <memory>
// a "standard" implementation of MyType
class MyTypeImpl
{
public:
virtual double operator()(double a) = 0;
virtual int implType() const = 0;
virtual void complexStuff() const = 0;
};
// some internal stuff common to all implementations
class MyTypeImplInternals
{
protected:
MyTypeImplInternals(int value):factor_{value}{}
int factor_;
void longCommonFunction() const{ std::cout << "I'm doing complex stuff common to all interfaces " << factor_ << "\n" ;}
};
// one specific implementation
class MyTypeImpl1: public MyTypeImpl, private MyTypeImplInternals
{
public:
MyTypeImpl1(int factor):MyTypeImplInternals{factor}{};
virtual double operator()(double a) override {return factor_*a;}
virtual int implType() const override {return 1;}
virtual void complexStuff() const override { longCommonFunction(); }
};
// a second implementation
class MyTypeImpl2: public MyTypeImpl, private MyTypeImplInternals
{
public:
MyTypeImpl2(int factor):MyTypeImplInternals{factor}{};
virtual double operator()(double a) override {return factor_*a;}
virtual int implType() const override {return 2;}
virtual void complexStuff() const override { longCommonFunction(); }
};
class MyTypeImplFactory
{
public:
static std::unique_ptr<MyTypeImpl>createMyTypeImpl(int implementationType)
{
switch(implementationType)
{
case 1:
return std::unique_ptr<MyTypeImpl> (new MyTypeImpl1(12));
case 2:
return std::unique_ptr<MyTypeImpl> (new MyTypeImpl2(22));
default:
throw std::runtime_error("implementation does not exist...\n");
return nullptr;
}
}
};
// my type
class MyType
{
public:
MyType(int implementationType)
{
implPtr_ = MyTypeImplFactory::createMyTypeImpl(implementationType);
}
MyType(MyType const& source)
: implPtr_{ MyTypeImplFactory::createMyTypeImpl(source.implType()) }
{
}
double operator()(double a){return (*implPtr_)(a);}
int implType() const {return implPtr_->implType();}
void complexStuff() const {implPtr_->complexStuff();}
private:
std::unique_ptr<MyTypeImpl> implPtr_;
};
class Obj
{
private:
MyType f;
public:
Obj(int dim):f{dim}{}
Obj(Obj&& sourceToMove) = default;
Obj(Obj const& source) = default;
void doStuff() {std::cout << "I'm doing stuff() " << f(2) << std::endl; f.complexStuff();}
};
int main()
{
Obj myObj{1}, myObj2{2};
myObj.doStuff();
myObj2.doStuff();
Obj myObj3{std::move(myObj2)}; // myObj2 now dead
Obj myObj4{myObj};
myObj3.doStuff();
myObj4.doStuff();
}
link to online compiler : http://cpp.sh/8rhyy
Here the implementations are very dumb ones to serve as an example. An application for this design could be for instance a Solver (Obj) that solves some kind of physics Equation (MyType) which exact definition depends on the dimensionality of the problem, equation in 1D space is not the same as in 2D or in 3D. Solver's code would be completely independent on Equation's dimensionality and also wouldn't have to deal with a pointer. Equation would hide its 1D, 2D, or 3D implementation from outside's world.
(was originally a post on code review that was put on Hold because to abstract)
This proposed class design appears to have an obvious problem. The polymorphic type is referenced by a std::unique_ptr:
std::unique_ptr<MyTypeImpl> implPtr_;
Obj's default copy constructor, and assignment operator will end up transferring the held pointer to the new object, leaving the std::unique_ptr in the original object staring at a nullptr. Not good.
At the bare minimum this should be either a std::shared_ptr, or Obj's copy constructor and assignment operator will need to instantiate a new implPtr_. Note that with the easy std::shared_ptr fix the result of the copy constructor and an assignment operator is having multiple instances of Obj referencing the same instance of MyTypeImpl, which may or may not be an issue.
A much simpler class design is simply have MyTypeImpl1 and MyTypeImpl2 be subclasses of Obj, implementing the required polymorphic behavior.
I just refactored your codes.
#include <iostream>
#include <memory>
// !abstraction
class MyType
{
public:
virtual double operator()(double a) = 0;
virtual int implType() const = 0;
virtual void complexStuff() const = 0;
};
// !!MyTypeImplInternals could be a super class of MyTypeImpl* if it has properties(such as factor_) or just some static functions.
class MyTypeImplInternals
{
public:
MyTypeImplInternals(int value):factor_{value}{}
int factor_;
void longCommonFunction() const{ std::cout << "I'm doing complex stuff common to all interfaces " << factor_ << "\n" ;}
};
// one specific implementation
class MyTypeImpl1: public MyType
{
MyTypeImplInternals internal_;
public:
MyTypeImpl1(int factor):internal_{factor}{};
virtual double operator()(double a) override {return internal_.factor_*a;}
virtual int implType() const override {return 1;}
virtual void complexStuff() const override { internal_.longCommonFunction(); }
};
// a second implementation
class MyTypeImpl2: public MyType
{
MyTypeImplInternals internal_;
public:
MyTypeImpl2(int factor):internal_{factor}{};
virtual double operator()(double a) override {return internal_.factor_*a;}
virtual int implType() const override {return 2;}
virtual void complexStuff() const override { internal_.longCommonFunction(); }
};
std::unique_ptr<MyType> createMyType(int implementationType)
{
switch(implementationType)
{
case 1:
return std::unique_ptr<MyType> (new MyTypeImpl1(12));
case 2:
return std::unique_ptr<MyType> (new MyTypeImpl2(22));
default:
throw std::runtime_error("implementation does not exist...\n");
return nullptr;
}
}
class Obj
{
private:
std::unique_ptr<MyType> f_;
public:
Obj(int dim):f_(createMyType(dim)){}
Obj(Obj&& sourceToMove) : f_(std::move(sourceToMove.f_)) {}
Obj(Obj const& source) : f_(createMyType(source.f_->implType())) {}
void doStuff() {std::cout << "I'm doing stuff() " << (*f_)(2) << std::endl; f_->complexStuff();}
};
int main()
{
Obj myObj{1}, myObj2{2};
myObj.doStuff();
myObj2.doStuff();
Obj myObj3{std::move(myObj2)}; // myObj2 now dead
Obj myObj4{myObj}; //!!Bad idea to share an implementation to more Objs.
myObj3.doStuff();
myObj4.doStuff();
}

Arrays of Pointers to Abstract Types

I have been experimenting with abstract types.
The code below gives me a desired effect.
class base{
public:
virtual void do_stuff() = 0;
};
class derived: public base{
public:
void do_stuff(){/*stuff*/}
};
class manager{
vector<shared_ptr<base>> ptrs;
public:
void add(base* ptr){
ptrs.emplace_back(ptr);
}
};
manager foo;
foo.add(new derived());
Fine and dandy, but it's awkward because the user is not only dealing with pointers, but has to use new without ever calling delete. My question is if there's a way I can implement this where the user of manager doesn't ever have to deal with pointers or new.
foo.add(derived()); //example
My attempts to implement this end up as:
class manager{
vector<shared_ptr<base>> ptrs;
public:
void add(base& ref){
ptrs.emplace_back(&ref);
}
};
But, the compiler says no known conversion from 'derived' to 'base&'. I have no idea how to make a reference to base compatible with a reference to derived. How do I get around this?
Pass unique_ptr
Your add function takes ownership of this object. A safe way of passing ownership is to pass unique_ptr.
Using a unique_ptr is fairly flexible because you can construct a shared_ptr from a unique_ptr or if you change your mind in the future you can store the unique_ptr directly.
class manager{
vector<shared_ptr<base>> ptrs;
public:
void add(std::unique_ptr<base> ptr){
ptrs.emplace_back(std::move(ptr));
}
};
manager foo;
foo.add(std::make_unique<derived>());
Using a temporary std::unique_ptr you avoid the owning raw pointer that is not exception safe. By using make_unique you can avoid writing new.
Live demo.
Pass a Factory
Another option if the caller really doesn't want to have to deal with any kind of pointer is to pass some sort of Factory that the add function uses to construct the object. The Factory could simply be a static create function on the derived class itself:
using Factory = std::function<std::unique_ptr<base>()>;
class manager{
std::vector<std::shared_ptr<base>> ptrs;
public:
void addUsing(const Factory& factory){
ptrs.emplace_back(factory());
}
};
class derived : public base {
public:
...
static std::unique_ptr<derived> create() {
return std::make_unique<derived>();
}
};
manager foo;
foo.addUsing(derived::create);
Live demo.
You can let your add() function be passed the arguments to be used in the construction of type T, where T is specified as the type of a subclass.
template <typename T, typename... TArgs>
void add(TArgs&&... args)
{
ptrs.emplace_back(std::make_shared<T>(std::forward<TArgs>(args)...));
}
Which can then be called as follows:
bm.add<derived_a>( "hello" ); // derived_a constructor takes a string
bm.add<derived_b>( 42 ); // derived_b constructor takes an int
Full example
#include <string>
#include <vector>
#include <memory>
class base
{
public:
virtual void f() = 0;
};
class derived_a : public base
{
public:
derived_a( std::string const& s ) : s_{ s } {}
void f() override { std::cout << "derived_a::string = " << s_ << '\n'; }
private:
std::string s_;
};
class derived_b : public base
{
public:
derived_b( int i ) : i_{ i } {}
void f() override { std::cout << "derived_b::int = " << i_ << '\n'; }
private:
int i_;
};
class base_manager
{
public:
template <typename T, typename... TArgs>
void add( TArgs&&... args )
{
ptrs.emplace_back( std::make_shared<T>( std::forward<TArgs>( args )... ) );
}
void print() { for ( auto& d : ptrs ) d->f(); }
private:
std::vector<std::shared_ptr<base>> ptrs;
};
int main()
{
base_manager bm;
bm.add<derived_a>( "hello" );
bm.add<derived_b>( 42 );
bm.print();
}
You can't pass a temporary (an r-value) to a non-const reference. Also you try to take the address of that temporary object, which will in the end produce a dangling pointer and undefined behavior.
Assuming you want to pass an object of unknown runtime type to the manager:
One thing you can do is using some sort of polymorphic copy mechanism (like a virtual clone method) and make an internal copy of the object on the heap (it has to be polymorphic, to avoid object slicing).
class base {
public:
virtual void do_stuff() = 0;
virtual shared_ptr<base> clone() const = 0;
virtual ~base()=default;
};
class derived : public base {
int data;
public:
derived() :data(0) {};
derived(const derived& other) :data(other.data)
{};
virtual shared_ptr<base> clone() const override {
return make_shared<derived>(*this);
};
void do_stuff() {/*stuff*/ }
};
class manager {
vector<shared_ptr<base>> ptrs;
public:
void add(const base& obj) {
ptrs.emplace_back(obj.clone());
}
};
int main() {
manager foo;
foo.add(derived());
}
without the clone, it would look something like this:
void add(const base& obj) {
if (typeid(obj)== typeid(derived) ){
ptrs.emplace_back(make_shared<derived>(static_cast<const derived&>(obj)));
}
else if (typeid(obj) == typeid(derived2)) {
...
}
Your original question seems to be concerned over the fact that the user/caller creates a pointer and hands it off and never deletes it. My example below, simply makes it explicit to the user that he can hand it off and forget about it. In otherwords, require the user to pass a shared_ptr...
#include <stdlib.h>
#include <vector>
#include <memory>
using namespace std;
class base{
public:
virtual void do_stuff() = 0;
};
class derived : public base{
public:
void do_stuff(){/*stuff*/ }
};
class manager{
vector<shared_ptr<base>> ptrs;
public:
void add(shared_ptr<base> ptr){
ptrs.emplace_back(ptr);
}
};
int main()
{
manager foo;
shared_ptr<derived> bp(new derived()); //require the user supply a smart pointer
foo.add(bp);
return 0;
}
This is simpler than the other posts, and may not be as forward thinking, but it does not require the derived class to implement additional base members. In many cases, it is may be enough.

Is it possible to adapt the "Prototype pattern" to rvalue references?

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.