How to create a spy class against the clone idiom in C++ - 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.

Related

Return unique_ptr with abstract class inside

I am trying to encapsulate details of the Engine implementation class. To do that I am returning std::unique_ptr of abstract class (IEngine in my case) instead of Engine. But I could not do that due to the compile error. I could return raw reference and it works but is that possible with unique_ptr? Thanks in advance.
class IEngine
{
public:
virtual ~IEngine() = default;
virtual void Start() = 0;
};
class Engine : public IEngine
{
public:
void Start() override {}
};
class Car
{
std::unique_ptr<Engine> m_engine;
public:
std::unique_ptr<IEngine>& Get() { return m_engine; } // Here is compile error
};
int main()
{
Car lambo;
}
std::unique_ptr<IEngine> is a different type to std::unique_ptr<Engine>, so you are asking to return a reference to a temporary object.
std::unique_ptr uniquely owns the object it points to, so even if you removed the reference, it would be incorrect to create a std::unique_ptr<IEngine> from the existing std::unique_ptr<Engine> that you presumably want to leave unchanged.
You shouldn't be exposing std::unique_ptr here. I'm not really sure you should be exposing IEngine here. I'm also confused as to why you need the concrete Engine type in Car, but the outside world needs mutable access to a pointer to IEngine.
I would instead expect something like:
class Car
{
std::unique_ptr<IEngine> m_engine;
public:
void TurnIgnition() { m_engine->Start(); }
};
I am trying to encapsulate details of the Engine implementation class.
Returning a non-const reference to a private member is rarely the right thing to do. In any case it is the opposite of data encapsulation. Once the caller has the reference they can do with it whatever they like. Returning a non const reference makes sense for convenience access methods like for example std::vector::operator[]. The purpose of std::vector::operator[] is not to hide the element from the caller. There are other ways to get your hands on it. Rather std::vector::operator[] is to make it more convenient to access elements. Encapsulation it is not.
It is also not clear why you want to return a unique_ptr from Get. When no transfer of ownership is desired no smart pointer needs to be returned.
I could return raw reference
Yes, thats perfectly fine:
#include <memory>
class IEngine
{
public:
virtual ~IEngine() = default;
virtual void Start() = 0;
};
class Engine : public IEngine
{
public:
void Start() override {}
};
class Car
{
std::unique_ptr<Engine> m_engine;
public:
const IEngine& Get() { return *m_engine; } // Here is compile error
};
int main()
{
Car lambo;
}

Can I somehow call the derived class method while looping through vector<shared_ptr<BaseClass>>?

I have the following problem:
class Component
{
public:
virtual void update(){};
};
class TestComponent : public Component
{
void update()override;
};
class GameObject
{
public :
void addComponent(Component& comp)
{
std::shared_ptr<Component> test = std::make_shared<Component>(comp);
components.push_back(test);
}
void GameObject::update()
{
for(auto comp : components)
{
//I want to call the derived update here without casting it to the derived class if possible
comp->update();
}
}
private:
std::vector<std::shared_ptr<Component>> components;
};
Somewhere else in my code:
GameObject go;
TestComponent comp;
go.addComponent(comp);
I would just assume that when I add an object to the vector of Components that I can simply call update on all of the vectors elements and it uses the overridden update of the object I passed into addComponent. So for my example above I expect the forloop to call the update of the TestComponent I added and not the baseclass update. But thats not whats happening so I assume I am missing something.
Or maybe my approach is just wrong in general. I am not really sure about my usage of a sharedpointer for this?
Any hints in the right direction would be appreciated.
There are no TestComponent objects in your vector. They are all Components.
void addComponent(Component& comp)
{
std::shared_ptr<Component> test = std::make_shared<Component>(comp);
components.push_back(test);
}
In this function, you create a new Component object that s a copy of the Component sub-object of the TestComponent object you passed in. This is known as object slicing.
You will need to either avoid copying the objects or implement some sort of cloneable interface.
To avoid copying the object, you can do something like this:
class GameObject
{
public:
void addComponent(std::shared_ptr<Component> comp)
{
components.push_back(comp);
}
// ...
};
int main() {
GameObject go;
std::shared_ptr<TestComponent> testComponent = std::make_shared<TestComponent>();
go.addComponent(testComponent);
}
In this case, main and go share ownership of a single TestComponent object. If you want to avoid that, you could implement a clonable interface so that objects know how to copy themselves:
class Component
{
public:
virtual void update(){};
virtual std::shared_ptr<Component> clone() const
{
return std::make_shared<Component>(*this);
}
};
class TestComponent : public Component
{
void update() override;
std::shared_ptr<Component> clone() const override
{
return std::make_shared<TestComponent>(*this);
}
};
class GameObject
{
public:
void addComponent(const Component& comp)
{
components.push_back(comp.clone());
}
// ...
};
int main()
{
GameObject go;
TestComponent comp;
go.addComponent(comp);
}
In this case, you still make a copy, but every class has to override the clone method.
As for the question about shared_ptr: std::shared_ptr is a smart pointer that shares ownership of an object between multiple owners. An object owned by one or more std::shared_ptrs is only destroyed when all of the std::shared_ptr objects sharing ownership of it are destroyed. If you don't need this behavior, then std::unique_ptr exists and will be somewhat more performant. std::unique_ptr models unique ownership. Only one std::unique_ptr object can ever reference an object at a time, and the object is destroyed when that std::unique_ptr is destroyed.
Either type of smart pointer could be used in this situation:
Use std::shared_ptr if you want a GameObject to be able to share ownership of its components with other owners (perhaps other GameObjects).
Use std::unique_ptr if you want a GameObject to have exclusive ownership of its components. In this case the GameObject could still allow other objects to access its components, but the components' lifetimes would be tied to the lifetime of the GameObject
To make your code compile just add another method, rest are fine . Since update method is virtual and the base class is non-abstract, both can call update without any issue.
void TestComponent::addComponent(const TestComponent & tcomp)
{
std::shared_ptr<Component> test = std::make_shared<TestComponent >(tcomp);
components.push_back(test);
}
Edited: For adding any component, derived or base class, use this way:
void TestComponent::addComponent(std::shared_ptr<Component> comp)
{
components.push_back(comp);
}

C++ Composition with abstract class

Lets say I have an abstract class that is expensive to create and copy:
class AbstractBase {
public:
AbstractBase() {
for (int i = 0; i < 50000000; ++i) {
values.push_back(i);
}
}
virtual void doThing() = 0;
private:
vector<int> values;
};
It has two subclasses FirstDerived:
class FirstDerived : public AbstractBase {
public:
void doThing() {
std::cout << "I did the thing in FirstDerived!\n";
}
};
and SecondDerived:
class SecondDerived : public AbstractBase {
public:
void doThing() {
std::cout << "I did the thing in SecondDerived!\n";
}
};
Further, I would like to make a class that utilizes FirstDerived or SecondDerived using composition (not aggregation). Meaning that I want ComposedOfAbstractBase to own whichever temporary is passed in. If I weren't using abstract classes in this class would look like: (in C++11)
class ComposedOfWhicheverDerived {
public:
ComposedOfWhicheverDerived(AbstractBase abstract_base) : abstract_base(std::move(abstract_base)) {;}
private:
AbstractBase abstract_base;
};
However, this does not work with abstract classes because I cannot ever create an instance of AbstractBase, even if I am careful about not passing in a temporary AbstractBase, like so:
ComposedOfWhicheverDerived a(FirstDerived());
To the compiler this is just as bad as:
ComposedOfWhicheverDerived b(AbstractBase());
Because I still have an instance of AbstractBase in the class declaration.
The next solution I came up with is:
class ComposedOfAbstractBase {
public:
ComposedOfAbstractBase(AbstractBase&& abstract_base) : some_derived_instance(abstract_base) {;}
private:
AbstractBase& some_derived_instance;
};
This works perfectly (even though I don't fully understand it)! Both of these instances are valid and work as intended:
ComposedOfAbstractBase a(FirstDerived());
ComposedOfAbstractBase b(SecondDerived());
It doesn't create a copy of whatever AbstractBase temporary is passed in, and storing a reference to an AbstractBase is allowed. Though at best the reference to an rvalue reference seems unclear: it does not convey that ComposedOfAbstractBase owns whichever temporary is passed in. In addition to that, it turns out that this solution seems to be sub-optimal. To show this I created this class:
class ComposedOfFirstDerived {
public:
ComposedOfFirstDerived(FirstDerived first_derived) : first_derived(std::move(first_derived)) {;}
private:
FirstDerived first_derived;
};
Which can only take in a FirstDerived, so we can apply the std::move to offload ownership of the temporary. I can make an instance like so:
ComposedOfFirstDerived c(FirstDerived());
Interestingly enough, this class consistently is 10% faster to create than ComposedOfAbstractClass.
Does anybody know what is going on here? Why is ComposedOfFirstDerived so much faster to create than ComposedOfAbstractBase? Is there a better way to do composition with abstract classes or am I stuck with a sub-optimal solution?
Sorry if this was a mouthful of a question. I appreciate anyone who takes the time to read through it and give a genuine answer, because I am beyond stumped!
ComposedOfAbstractBase is not a solution. You're holding a dangling reference.
Since AbstractBase is, as the name suggests, abstract - you cannot hold one by value. You can only hold one by reference or by pointer. Since a reference cannot own the object, that leaves you with the pointer. And the modern way of owning a pointer is to use unique_ptr:
class ComposedOfAbstractBasePtr {
public:
ComposedOfAbstractBasePtr(std::unique_ptr<AbstractBase> p)
: some_derived_instance(std::move(p))
{ }
private:
std::unique_ptr<AbstractBase> some_derived_instance;
};
Note that your AbstractBase does not have a virtual destructor. You should fix that.

Making a copy of an object of abstract base class

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

How to create class objects dynamically?

Let's say I have a class box, and a user can create boxes. How to do it? I understand I create objects by className objectName(args); but how to do it dynamically, depending on the user input?
The correct answer depends on the number of different classes of which you want to create the instances.
If the number is huge (the application should be able to create an instance of any class in your application), you should use the reflection functionality of .Net. But, to be honest, I'm not a big fan of using reflection in business logic, so I would advise not to do this.
I think that in reality you have a limited number on classes for which you want to create instances. And all the other answers make this assumption. What you actually need is a factory pattern. In the next code I also assume that the classes of which you want to create instances, all derive from the same base class, let's say Animal, like this:
class Animal {...};
class Dog : public Animal {...}
class Cat : public Animal {...}
Then create an abstract factory which is an interface that creates an animal:
class IFactory
{
public:
Animal *create() = 0;
};
Then create subclasses for each of the different kinds of animals. E.g. for the Dog class this will become this:
class DogFactory : public IFactory
{
public:
Dog *create() {return new Dog();}
};
And the same for the cat.
The DogFactory::create method overrules the IFactory::create method, even if their return type is different. This is what is called co-variant return types. This is allowed as long as the return type of the subclass's method is a subclass of the return type of the base class.
What you can now do is put instances of all these factories in a map, like this:
typedef std::map<char *,IFactory *> AnimalFactories
AnimalFactories animalFactories;
animalFactories["Dog"] = new DogFactory();
animalFactories["Cat"] = new CatFactory();
After the user input, you have to find the correct factory, and ask it to create the instance of the animal:
AnimalFactories::const_iterator it=animalFactories.find(userinput);
if (it!=animalFactories.end())
{
IFactory *factory = *it;
Animal *animal = factory->create();
...
}
This is the typical abstract factory approach.
There are other approaches as well. When teaching myself C++ I wrote a small CodeProject article about it. You can find it here: http://www.codeproject.com/KB/architecture/all_kinds_of_factories.aspx.
Good luck.
The following factory method creates Box instances dynamically based on user input:
class BoxFactory
{
public:
static Box *newBox(const std::string &description)
{
if (description == "pretty big box")
return new PrettyBigBox;
if (description == "small box")
return new SmallBox;
return 0;
}
};
Of course, PrettyBigBox and SmallBox both derive from Box. Have a look at the creational patterns in the C++ design patterns wikibook, as one of them probably applies to your problem.
In C++, it is possible to allocate objects using automatic (stack) and dynamic (heap) storage.
Type variable_name; // variable_name has "automatic" storage.
// it is a local variable and is created on the stack.
Type* pointer_name = NULL; // pointer_name is a "pointer". The pointer, itself,
// is a local variable just like variable_name
// and is also created on the stack. Currently it
// points to NULL.
pointer_name = new DerivedType; // (where DerivedType inherits from Type). Now
// pointer_name points to an object with
// "dynamic" storage that exists on the heap.
delete pointer_name; // The object pointed-to is deallocated.
pointer_name = NULL; // Resetting to NULL prevents dangling-pointer errors.
You can use pointers and heap-allocation to dynamically construct objects as in:
#include <cstdlib>
#include <iostream>
#include <memory>
class Base {
public:
virtual ~Base(){}
virtual void printMe() const = 0;
protected:
Base(){}
};
class Alpha : public Base {
public:
Alpha() {}
virtual ~Alpha() {}
virtual void printMe() const { std::cout << "Alpha" << std::endl; }
};
class Bravo : public Base {
public:
Bravo() {}
virtual ~Bravo() {}
virtual void printMe() const { std::cout << "Bravo" << std::endl; }
};
int main(int argc, char* argv[]) {
std::auto_ptr<Base> pointer; // it is generally better to use boost::unique_ptr,
// but I'll use this in case you aren't familiar
// with Boost so you can get up and running.
std::string which;
std::cout << "Alpha or bravo?" << std::endl;
std::cin >> which;
if (which == "alpha") {
pointer.reset(new Alpha);
} else if (which == "bravo") {
pointer.reset(new Bravo);
} else {
std::cerr << "Must specify \"alpha\" or \"bravo\"" << std::endl;
std::exit(1);
}
pointer->printMe();
return 0;
}
Related: the "Factory" object-oriented design pattern