Making a copy of an object of abstract base class - c++

If I have a pointer to an object that derives from an abstract base class (so I cannot create an new object of that class), and I wish to make a deep copy of said object, is there a more concise way of accomplishing that than to have the abstract base class create a new pure virtual copy function that every inheriting class has to implement?

No, but the copy method does not have to be painful:
class Derived : public Base
{
public:
Base *copy() const
{
return new Derived(*this);
}
};
(assuming you already have a copy constructor, which, if you need a deep copy, you'll have).

The suggested 'copy', more usually called 'clone' is the normal approach. An alternative would be a factory and dispatch using rtti to find the right handler to then call the copy constructor on the derived type.
struct Abc
{
virtual void who() const = 0;
};
struct A : Abc
{
virtual void who() const { std::cout << "A" << std::endl;}
};
template<class T>
Abc* clone(Abc* abc)
{
T* t = dynamic_cast<T*>(abc);
if (t == 0)
return 0;
return new T(*t);
}
struct B : Abc
{
virtual void who() const { std::cout << "B" << std::endl;}
};
typedef Abc* (*Cloner)(Abc*);
std::map<std::string, Cloner> clones;
void defineClones()
{
clones[ typeid (A).name() ] = &clone<A>;
clones[ typeid (B).name() ] = &clone<B>;
}
Abc* clone(Abc* abc)
{
Abc* ret = 0;
const char* typeName = typeid(*abc).name();
if (clones.find(typeName) != clones.end())
{
Cloner cloner = clones[typeName];
ret = (*cloner)(abc);
}
return ret;
}
void test ()
{
defineClones();
Abc* a = new A;
Abc* anotherA = clone(a);
anotherA->who();
Abc* b = new B;
Abc* anotherB = clone(b);
anotherB->who();
}
Whilst the above works, the sheer fact it uses rtti would be enough to persuade most to go the normal approach. However, it there was a reason preventing changes to the base class, it might be useful.
It this efficient? The marginal cost of adding a new type is truly a one-liner. The catch is that it will be easy to forget to add that line with each new class. Or you can see it as an upside that all the clone code lives in a single file and we don't have to change the supported hierarchy to handle it.

A while back someone in comp.lang.c++ asked how to automatically create a clone() function. Someone else provided an idea upon which I expanded. None of it is tested code and I've never actually tried it...but I think it works: http://groups.google.com/group/comp.lang.c++/browse_thread/thread/c01181365d327b2f/9c99f46a8a64242e?hl=en&ie=UTF-8&oe=utf-8&q=comp.lang.c%2B%2B+noah+roberts+clone&pli=1

Related

How to construct a template class type that can be substituted for subclasses and then called generically?

I have 10 Coin types: BTC, ETH, Shift etc. For this I have a superclass "Coin" and subclasses for each of those coins. Then I have a pointer to a "Coin" type, so that I can call each of the subclasses no matter what subtype they are.
Problem is, I only know how to do this in Java and not in C++. I have a hard time searching for the correct terms, because I don't really know what to search for other than "generics". What I want is something like this:
// Superclass
class Coin {
public:
virtual void handleCoin();
};
// Subclass
class BTC: public Coin {
void handleCoin();
}
BTC::BTC() = default;
BTC::~BTC() = default;
BTC::handleCoin() {
std::cout << "handling BTC" << std::endl;
}
// Subclass
class ETH: public Coin {
void handleCoin();
}
ETH::ETH() = default;
ETH::~ETH() = default;
ETH::handleCoin() {
std::cout << "handling ETH" << std::endl;
}
// Execute
int main() {
Coin* coin;
coin = BTC();
coin.handleCoin();
coin = ETH();
coin.handleCoin();
return 0;
}
I want this to print:
handling BTC
handling ETH
I know I need to work with templates, but I cannot find a specific example of this specific case.
Also, my constructors don't take arguments, so I guess my template declaration would be something like
template<>
Yet all the examples I see work with
template<typename T>
and then use type T as function arguments like calling
max<float, float>
max<double, double>
But that's not what I'm looking for. Is there a way to translate this example above to working C++ code?
From the code posted I don't see a need for templates, virtual methods work without templates. To fix your code in main you need to use pointers/references and also have a virtual destructor.
class Coin {
public:
virtual void handleCoin();
virtual ~Coin()=default;
};
class BTC: public Coin {
public:
BTC::BTC() = default;
//Destructor of a derived class is automatically virtual if the base class's one is.
void handleCoin();
}
// Subclass
class ETH: public Coin {
void handleCoin();
ETH::ETH() = default;
//Still virtual even if you specify otherwise
ETH::~ETH() = default;
}
int main() {
Coin* coin;
coin = new BTC();//Returns BTC* <--pointer
coin->handleCoin();
delete coin;//Calls Coin::~Coin() -> thus the need for virtual so BTC::~BTC is called instead.
coin = new ETH();
coin->handleCoin();
delete coin;//Same, calls ETH::~ETH()
return 0;
}
Manual memory management is error-prone, from C++11 there's a better approach which should be strongly preferred:
int main() {
std::unique_ptr<Coin> coin;//Hides the pointer, but still has pointer-like semantics
coin = std::make_unique<BTC>();
coin->handleCoin();
//Automatically frees old memory
coin = std::make_unique<BTC>();
coin->handleCoin();
//Calls unique ptr's dtor because coin is local variable, which again frees the memory correctly.
return 0;
}

How to create a spy class against the clone idiom in C++

Coming from the Java/PHP world, I am still new to C++. Some simple things to do in other languages are a bit trickier to do in C++.
My main issue is the following. Right now, I have a class (ie. "Something") for which the constructor is injected with a virtual class dependency (ie. a children of "Base"). Then, the constructor stores this injected instance in a unique_ptr<Base> class field (using the clone idiom). This works well at the application level, everything seems to works as expected. Here is the sample code:
class Base {
public:
virtual std::unique_ptr<Base> clone() = 0;
virtual void sayHello() const = 0;
};
class Something {
public:
explicit Something(Base &base) { this->base = base.clone(); }
void sayHello() const { base->sayHello(); }
private:
std::unique_ptr<Base> base;
};
But to make sure it does, I wrote unit tests to test its behavior. In those tests, I want to assert the injected dependencies methods are actually called. So logically, injecting a "spy" dependency should do the trick.
Here is what I did at first:
class SpyDerived : public Base {
public:
explicit SpyDerived() = default;
SpyDerived(const SpyDerived &original) { this->someState = original.someState; }
std::unique_ptr<Base> clone() override { return std::make_unique<SpyDerived>(*this); }
void sayHello() const override { std::cout << "My state: " << someState << std::endl; }
void setSomeState(bool value) { this->someState = value; }
private:
bool someState = false;
};
This is the main function I use to this this out:
int main() {
SpyDerived derived;
Something something(derived);
derived.setSomeState(true);
something.sayHello();
}
For obvious reasons, someState value on print is always false. I get that the Derived instances in Something is a new copy of Derived and no longer the one that was created in the main function.
So basically, what I am trying to achieve here is to have the Something class always use the SpyDerived instance created in the main function. Is there any way I could make this work. I am trying to avoid changing the design just for test purposes.
I am using MSVC 2015 to compile the code. Keep in mind that smart pointers, C++ idioms, copy/move constructors are fairly new concepts for me.
Thanks for your help.
Well, do you want to clone your instance, or simply reference that instance?
The clone idiom is made to copy the instance of a class, making the new instance independent of the old instance.
You are basically making this, in term of PHP:
<?php
interface Base {
public function sayHello();
}
class SpyDerived implements Base {
private $someState = false;
public function sayHello() {
echo 'My state: ' . $this->someState;
}
}
class Something {
public __construct(Base $base) { $this->base = clone $base; }
public function sayHello() { $this->base->sayHello(); }
private $base = null;
}
$derived = new SpyDerived;
$something = new Something($derived);
$derived->setSomeState(true);
$something->sayHello();
?>
You see this? $base is cloned. Something::$base is a copy.
So in PHP, what would you do to solve that problem?
Simple! Remove that clone, no copies!
Well, in C++, this is the same thing. If you have an object pointer and don't want to clone it, don't actually call the clone method.
We will change your class to, like PHP, contain a reference to the object. We will start by making Something contain a non owning reference:
class Something {
public:
explicit Something(Base& b) : base{b} { }
void sayHello() const { base.sayHello(); }
private:
// we simply contain a reference to the base
Base& base;
};
In C++, a reference does not own the object. If the object is destroyed, all reference pointing to that object will point to a dead object.
As you can notice, your tests stays the same and work:
int main() {
SpyDerived derived;
Something something(derived);
derived.setSomeState(true);
something.sayHello();
}
If you want Something be the owner of Base, then use std::unique_ptr<Base>:
class Something {
public:
explicit Something(std::unique_ptr<Base> b) : base{std::move(b)} { }
void sayHello() const { base->sayHello(); }
private:
std::unique_ptr<Base> base;
};
Beware that the ownership of base should be transferred from the caller to the something class. That transfer is express through that std::move thing, because we are moving the ownership of that resource.
Then in your tests:
int main() {
auto derived = std::make_unique<SpyDerived>();
// We want to keep a non-owning reference of derived
// The star (*) operator of std::unique_ptr returns a reference to the pointed object
auto& derived_ref = *derived;
// We transfer the ownership of derived to the `Something`
Something something(std::move(derived));
// Since derived is a reference to the object pointed by our pointer,
// It will affect the value we found in `Something`, because they are
// both pointing to the same instance.
derived.setSomeState(true);
something.sayHello();
}
Since Something is owner of derived, the non-owning reference derived_ref will point to a dead object if something dies before.

How to properly deep copy 2D array of abstract class array in C++ with C style

I have abstract class Figure. Then I have an array of it, and I want to resize it, but not sure how to do it.
Figure ** arr; //lets assume it's filled with some data
Figure ** temp = new Figure * [size + 1];
for(int i =0; i < size; ++i)
{
temp[i] = new Figure(); //it doesn't let me to create object from the abstract class
temp[i] = arr[i] //if I do this, once I delete arr, I will lose temp as well
}
Any help?
The problem
If Figure is an abstract class, you can't instantiate it:
temp[i] = new Figure(); // ouch: can't do: strictly forbidden
and even if you could, you couldn't copy such a polymorphic class without suffering from slicing:
temp[i] = arr[i]; // arr[i] is a derivate of Figure and might have a different size for example
The solution
To solve your issue, you must define a virtual clone() member function:
class Figure {
...
Figure* clone() = 0;
};
You would then implement this function, for example like this:
class Square : public Figure {
...
Figure* clone() override {
return new Square(*this);
}
};
You would change your deep copy to to:
temp[i] = arr[i].clone();
The improvement
The risk of returning a freshly allocated clone is to have a memory leak. So
instead of using raw pointers you could use shared_ptr<Figure> or unique_ptr<Figure> (not only as return argument of the cloning function but also as element of the array.
By the way, you could also consider changing the array to a vector, thus avoiding extra manual memory allocation (and later deletion) of the temp.
The answer is to take advantage of the polymorphic behavior the class hierarchy provides and make a virtual function to create the copy. For example, clone is a commonly named function for this.
Example Code
#include <iostream>
#include <memory>
#include <vector>
class Base
{
public:
virtual ~Base() {}
virtual Base* clone() const = 0;
virtual void print() const = 0;
};
class D1 : public Base
{
public:
virtual D1* clone() const override { return new D1(*this); }
virtual void print() const override { std::cout << "D1\n"; }
};
class D2 : public Base
{
public:
virtual D2* clone() const override { return new D2(*this); }
virtual void print() const override { std::cout << "D2\n"; }
};
int main()
{
std::vector<std::unique_ptr<Base>> original;
original.push_back(std::make_unique<D1>());
original.push_back(std::make_unique<D2>());
std::vector<std::unique_ptr<Base>> copy;
for (const auto& o : original)
{
copy.push_back(std::unique_ptr<Base>(o->clone()));
}
for (const auto& c : copy)
{
c->print();
}
return 0;
}
Example Output
D1
D2
Live Example
All of this can be achieved just the same with C style arrays however this question is tagged with C++.
Note: Even though the derived classes have a different signature for their respective clone functions this is perfectly valid. See covariant return type for more information.

Are there metaclasses or class reference in D?

Are there any system of classe reference in D? To be more accurate I look for the equivalent of the Delphi
TMyClassRef = class of TMyClass;
This would be used for a factory (just like in the Object but without using the class name):
// ideally
void AddNew(*TBaseClass APtr, /*?class_ref_type?*/ AClassType)
{
*APtr = new AClassType;
}
Currently I do this:
void AddNew(*TBaseClass APtr)
{
*APtr = new typeof(*APtr);
}
But the problem is that typeof() returns always TBaseClass and never a sub class of TBaseClass (when a sub class is passed as parameter). This is clearly a case where class references would be used in Delphi but the D language doesn't seem to have such a system.
Maybe I'm completely missing the idea in Delphi, but this seems to be what a templates are for:
import std.stdio;
class Parent {
string inherited() {
return "Hello from parent";
}
override string toString() {
return "Hello from parent";
}
}
class Child : Parent {
override string toString() {
return "Hello from child";
}
}
void add(C, P)(P* ptr) {
*ptr = new C;
}
void main() {
Parent t;
writeln(t); // prints null
add!Child(&t);
writeln(t); // prints Hello from child
writeln(t.inherited()); // prints Hello from parent
}
This way you pass in the type you want to instantiate instead of an instantiated object of that type. This should generate compile errors if C is not a child of P in add().
Edit:
If you want to be more specific with add, you could do this:
void add(T : Parent)(Parent* ptr) {
*ptr = new T;
}
To make things nicer, use an out parameter to be more idiomatic:
void add(T : Parent)(out Parent ptr) {
ptr = new T;
}
void main() {
Parent p;
add!Child(p);
}
D has no class references in the Delphi way as far as I have understood Delphi concept. If you need to make a run-time decision about object construction, object.TypeInfo may help you.
You can retrieve TypeInfo for a variable via typeid construct:
import std.stdio;
class Base
{
void f()
{
writeln("Base");
}
}
class Descendant : Base
{
override void f()
{
writeln("Descendant");
}
}
Base makeNew(Base other)
{
// cast is needed because create() returns plain Object
// we can be sure it is Base at least, though, because it was crated from Base
return cast(Base)typeid(other).create();
}
void main()
{
Descendant source = new Descendant;
Base target = makeNew(source);
// prints "Descendant"
target.f();
}
Is this code sample similar to what you want?
D generally has a very clear differentiation between run-time actions and compile-time ones. typeof works on compile-time and thus can't query "real" class type in case of hierarchies.

How to provide more than one overrides for one virtual function

I have the following classes :
class A {
};
class B : public A {
};
class P {
private:
std::list<A*> l
protected:
virtual void DoIt(A* a) = 0;
public:
void WorkerThread() { for (it=l.begin(); it!=l.end(); it++) DoIt(*it); }
};
class Q : public P
{
protected:
void DoIt(A* a) { print("false"); }
void DoIt(B* b) { print("true"); }
};
Unfortunately, DoIt(B* b) will never get called.
DoIt(A* a) will always be called even if I add B objects to the list.
What can I do to make DoIt(B* b) called ?
Is it possible to achieve this if B does not know Q ?
Is it possible to achieve this if without dynamic cast ?
Thank you
Well, nobody's really directly answered your question (well, heavyd tried) so I will. Some other "answers" here are actually more helpful for fixing your problem though.
The issue is that void DoIt(B*) is NOT an override of the virtual function DoIt(A*). It's an overload. There's a HUGE difference.
When you say that DoIt(B*) is not called when you pass a B* I have to assume that you're holding references or pointers to you Q through a pointer to something higher up the higherarchy. In those cases the static name resolution only finds DoIt(A*) and since B* is-a A* it gets upcasted and that's the version that gets called. Since it is virtual the override in Q is what gets called.
If you had a pointer to Q as a pointer to Q though, and called DoIt with a B* the DoIt(B*) function should get called. At this point, double dispatch is not needed and is not used.
You need double dispatch when you have two abstract types and a function that must behave differently based on the concrete types of both abstractions. This is what you're attempting to do when you call DoIt with B on Q at a higher level than static naming provides. There are too many methods that answer different needs to be able to suggest one solution over another in your case, don't really know what you're trying to solve. In fact, you might not even need it! A better approach for you might be to implement DoIt(B*) as a virtual function in the top of your higherarchy.
I would suggest that you get Andre Alexandrescu's book, Modern C++ Design, and look it over. He explains a pretty darn cool visitor implementation as well as a multiple dispatch mechanism that scales. Don't stop there though, there's other great implementations that can answer the question differently.
Good luck.
You are looking for a double dispatch mechanism that is not built into the language. There are different approaches on how this can be implemented based on the visitor pattern. Google for double-dispatch in C++. Note that this is a patch and not easily extended to big hierarchies:
struct visitor;
struct A {
virtual void accept( visitor& v ) { v(*this); }
};
struct B {
virtual void accept( visitor& v ) { v(*this); }
};
struct visitor {
virtual void operator()( A& ) = 0;
virtual void operator()( B& ) = 0;
};
struct myvisitor : visitor {
void operator( A& ) { std::cout << "A" << std::endl; }
void operator( B& ) { std::cout << "B" << std::endl; }
};
int main() {
std::vector<A*> data = ...
myvisitor v;
for ( std::vector<A*>::iterator it = data.begin(), end = data.end(); it != end; ++it )
{
(*it)->accept( v );
}
}
The usual mechanism will be used and accept will be dispatched to the final overrider of the method, which in turn will call the visitor method. Now, at that point, the static type of the argument to the visitor operator() is in fact the actual type that you want to call the function with.
DoIt(B* b) will never get called because you are never passing in objects of type B*, every time you call DoIt, at least in the given code, you are passing in objects of type A*.
Consider the situation where the override of Doit(A* a) did not exist. Your current code would not compile because it the compiler cannot implicitly cast an object of type A* to B*.
What are you expecting the behaviour to be if someone passes in an A* but the underlying type is really a B?
You might be looking for something like this:
class A
{
public:
virtual ~A() {}
virtual bool isB() const { return false; }
};
class B : public A
{
public:
bool isB() const { return true; }
};
void Q::DoIt( A* a )
{
print( a->isB() ? "true" : "false" );
}
You're looking for multiple dispatch or multimethods. Wikipedia has a nice example for c++; link here.
What you are trying to do is known as multiple dispatch and won't work in C++ because function overloading is static. Take a look at the wikipedia article for some possible work arounds.
For example, if you don't want the logic for the DoIt functionality in the A and B classes themselves as a virtual function then you could use the dynamic_cast method:
class A {
};
class B : public A {
};
class P : protected std::list<A*>
{
protected:
virtual void DoIt(A* a) = 0;
public:
void WorkerThread() { for (it=begin(); it!=end(); it++) DoIt(*it); }
};
class Q : public P
{
protected:
void DoIt(A* a) {
if(B *b = dynamic_cast<B*>(a)) {
// It's a B*, you can "use" b here
print("true");
} else {
// It's an A*
print("false");
}
}
};