I have an abstract base class named component.
It has derived non-abstract classes like resistor, generator etc...
In my circuit class, I have an heterogenous std::vector<sim::component*> named component_list, which I use to handle all the components inserted in the circuit.
Then I have the following function :
void circuit::insert(sim::component& comp, std::vector<sim::node*> nodes)
In the function definition, I want to copy the component named comp
in order to insert a pointer to it in my component_list
(so that I can manage its lifetime)
I tried something along those lines :
sim::component *copy = new sim::component(comp)
but of course, sim::component is abstract and I can't instanciate it
How can I make a copy of the object, which real class is unknown at compile-time ?
One traditional way to solve it is to let the objects clone themselves, plus a bit of CRTP.
I. First, you make your abstract class clonable:
struct Component {
virtual Component *clone() const = 0;
virtual ~Component() {}
};
Now, every Component should define its own implementation of clone().
II. Which is easily automated via CRTP:
template<class Concrete> struct CompBase: Component {
Component *clone() const {
return new Concrete(static_cast<Concrete const &>(*this));
}
virtual ~CompBase() {}
};
struct Generator: CompBase<Generator>; // already has clone() defined
Note that I've used plain pointers in the example, though it is generally recommended to use more smart analogs. std::unique_ptr would fit quite nice, along with std::make_unique.
Which creates another opportunity: with unique_ptr you can even forget about cloning and simply pass unique_ptrs as objects, each one with its own concrete class instance inside, and store them in a vector.
Related
I have Derived Classes that inherit from a Base class with virtual functions. Im using smart pointers(shared_ptr) in order to create the objects because i want the objects to be appended into a vector. But i noticed my code to be repetitive with handling to objects to do certain tasks so i thought a template could be solution to improve my code.
This is my attempt so far(not the exact code, simplified):
class Base{
public:
virtual ~Base(){}
virtual void display_message() = 0;
};
class DerivedA : public Base{
DerivedA(){}
};
class DerivedB : public Base{
DerivedB(){}
};
//THE template-
//<hold the smart pointer that points to different derived objects>
template<typename T1>
class HandleInstances{
private:
vector<T1> ObjectVector;
//the iterator
T1 sp_base;
public:
HandleInstance(const T1 & sp){
sp_base = sp; // set smart pointer
}
//somefunctions
//this is what i need to figure out
void AddToVector(){
ObjectVector.push_back(sp_base(new 'The derived class') );
}
};
The AddToVector functions is the problem here. in order to add an element of an object i have to do this push_back( "the smart pointer"( new "the class" ));. how do i let the template accept the class (not an object) and implement it to the function of push_back() ?
You are trying to use an object as a class, and that will not work (unless the object has an operator() that returns the correct object, but I digress).
Try instead:
void AddToVector(){
ObjectVector.push_back(T1(sp_base));
}
This will create a new object, and invoke the copy-constructor of the new object and pass sp_base to it. So in essence create a copy of sp_base.
This is a challenging one - why? Because templates operate as a sort of preprocessing step in C++ by dynamically constructing variants of classes based on their template parameter.
In other words, shared_ptr<DerivedA> and shared_ptr<DerivedB> have no relationship to each other whatsoever, because in C++, templates essentially make them like 2 separate class declarations - unrelated types.
The pointers they contain are both descendants of the base class, but the shared_ptrs themselves might as well be a Vector<Bool> and a Foo. It doesn't matter that DerivedA and DerivedB inherit from a single base class, their template-generated classes do not.
That being said, you do have some flexibility: if you put a factory function in your classes' interface, like this:
class DerivedA : public Base{
public:
static shared_ptr<DerivedA> construct{
return shared_ptr<DerivedA>(new DerivedA());
};
};
....similar for DerivedB
then you can do something like this:
template<typename T>
class HandleInstances{
private:
vector<shared_ptr<T> > ObjectVector;
public:
//this is what i need to figure out
void AddToVector(){
ObjectVector.push_back(T::construct());
}
};
and you should be OK. What you're doing is giving each class a function to make up for the fact that the class itself can't be stored to make objects later. Notice:
The template parameter in HandleInstances is the base type, not a shared_ptr type.
Construct is returning different types in DerivedA and DerivedB.
Base has no declaration of construct - because these functions do not return compatible types, they are not inherited from Base.
You still can't mix and match types in your ObjectVector, if that's what you were hoping - but you were never going to be able to do that anyway. (Bonus: it is possible if you use more types to wrap your types and handle this: see boost::any
Make the function a template as well:
template<typename T2>
void AddToVector(){
ObjectVector.push_back(smart(new T2));
}
I'm assuming you meant to have a smart pointer in the push_back rether than your member variable sp_base.
If I want to clone a polymorphic object in C++ (i.e. an instance of a class A which is derived from some other class B), the easiest way seems to give B a virtual clone member function, that has to be overridden by A and looks like this
A* clone(){
return new A(*this);
}
My problem is, that I find this unnecessary boilerplate code, as this is almost always needed, if one wants to use run-time polymorphic features of C++. How can it be circumvented?
Thanks
Why I need this:
My use case can be abstracted to the following example:
I have a class Integral, which evaluates the integral of some function. Do do this, they have a member which is a pointer to the class MathFunction. This abstract class contains a pure virtual function evaluate which takes one argument. I I wanted to implement the power function I would create a class PowFunction : class MathFunction. This class would have a member exponent and the function evaluate would look like this:
double evaluate(x){
return pow(x,exponent);
}
As stated the member MathFunction of class Integral has to be polymorhpic, which requires it to be a pointer. To answer the questions of the commenters with another question. Why wouldn't I want to be able to make copies of MathFunction objects?
I really want the Integral to "own" its MathFunction, meaning, that it can alter the parameters (like exponent) without changing the MathFunction of any other Integral object. This means every Integral needs to have its own copy. This requires a clone() function for MathFunctions, doesn't it?
One alternative i thought of: If several Integral objects can share the same MathFunction via a pointer to the same address, I could create copies of Integral objects without the need to copy the MathFunction. But in this case I would have to make all the properties const or somehow readonly, which is not very elegant either. Also, which Integral object should handle delete the MathFunction object?
Why you need this:
Are you seriously saying, that as soon as you work with polymorphic objects you don't ever need a copy operation? What makes polymorphic object different from other objects in this respect?
Using this argumentation, you could also throw the copy constructor and copy assignment operator out of the C++ standard!
Reduce the need to clone polymorphic objects. Really, I rarely find the need for this in my own code, and the comments on the question suggest that I'm hardly alone in the opinion that if you find yourself cloning everything, you're probably designing it wrong.
Of course, never to be unhelpful, you could indeed use the Curiously Recurring Template Pattern.
template<typename T> struct Clone {
virtual T* clone() { return new T(static_cast<const T&>(*this)); }
};
I handled this issue with a macro... it's ugly, but it works to avoid inconsistencies.
/** An interface that can be inherited by any class that wants to provide a Clone()
* method that will return a copy of itself.
*/
class ICloneable
{
public:
ICloneable() {}
virtual ~ICloneable() {}
virtual ICloneable * Clone() const = 0;
};
#define DECLARE_STANDARD_CLONE_METHOD(class_name) virtual ICloneable * Clone() const {new class_name(*this);}
[...]
public MyCloneableClass : public ICloneable
{
public:
MyCloneableClass() {}
DECLARE_STANDARD_CLONE_METHOD(MyCloneableClass);
};
I want to put any kind of Object (Object, Object etc.) into one shared_ptr. So I created base class and use shared_ptr.
But, how can I declare
T getMember();
within the base class so I can call ObjectBase.getMember?
class ObjectBase
{
public:
//virtual getMember HOWTO?
};
template<typename T>
class Object : public ObjectBase
{
public:
Object(T x):member(x) { }
T getMember() { return member; }
private:
T member;
};
You can't. How should such a declaration look, that it can return all kinds of types? It's just not possible. You'd have to cast the ObjectBase* to the correct Object<T>* and then use the getMember function. It's only possible if all T share a common base class, so you could return a pointer to that. But that would put a strict constraint on T.
That cannot be done. The compiler must know upfront how many different virtual functions (and overloads) will be available, but in your case you are considering adding new virtual member functions on demand based on new potential instantiations of the derived type.
In most cases, keeping completely unrelated objects in the same container is not a good design option, but for the few cases where it actually is, you can use variant types (consider boost::any or boost::variant, depending on your actual requirements. That is a bundled up, tested implementation of a variant type that you might be able to directly use.
I have an abstract base-class to enforce some subclasses to overload the << operator.
I am storing a bunch of pointers to instances of these subclasses in an std::stack... At some point I wish to duplicate the top item of the stack (and push it on top).
The problem is, I cannot instantiate an abstract class. And obviously since I want to do this for each of my subclasses, I won't know the type...
I wonder if this is even possible without adding another pure virtual method (say 'Base *clone() = 0') and implement it in each of my subclasses? Surely there must be a cleaner way.
I think you actually need a Clone method in this case. You want to dynamically copy the subclass item at runtime, and the normal way to change behavior at runtime is virtual methods. Without using some virtual method you would have no way of figuring out which child it is. You could probably use CRTP to automatically generate that Clone for you though:
// Totally uncompiled and untested.
class Base
{
public:
virtual Base* Clone() const = 0;
};
template <class T>
class Child : public Base
{
public:
virtual Base* Clone() const { return new T(*static_cast<T*>(this)); }
protected:
Child(); // Can't instantiate directly
Child(const Child& right); // Can't instantiate directly
};
class Grandchild : public Child<Grandchild>
{
// Clone should do the right thing.
};
Do you mean making a copy of the class, rather than duplicating the pointer.
You will need to either implement your own typing. in other words have a virtual function that returns the class type and then create the appropriate class
Or enable RTTI (Run-Time Type Information) to do the same thing. because RTTI effects every class its possibly more efficient to create your own typeof method.
Then you can
Pop the pointer
Get the type
Instantiate the correct class using
a copy constructor probably in a
switch
Push both back onto the stack
psuedocode
base* ptr = stack.pop()
base *copy
switch (ptr->typeof()) {
case class1type : copy = new class1(ptr) break;
case class2type : copy = new class2(ptr) break;
...
}
stack.push (ptr)
stack.push(copy)
DC
I'm experiencing a challenging problem, which has not been solvable - hopefully until now. I'm developing my own framework and therefore trying to offer the user flexibility with all the code complexity under the hood.
First of all I have an abstract base class which users can implement, obviously simplified:
class IStateTransit
{
public:
bool ConnectionPossible(void) = 0;
}
// A user defines their own class like so
class MyStateTransit : public IStateTransit
{
public:
bool ConnectionPossible(void){ return true; }
}
Next, I define a factory class. Users can register their own custom state transit objects and refer to them later by simply using a string identifier they have chosen:
class TransitFactory : public Singleton<TransitFactory>
{
public:
template<typename T> void RegisterStateTransit(const string& name)
{
// If the transit type is not already registered, add it.
if(transits.find(name) == transits.end())
{
transits.insert(pair<string, IStateTransit*>(name, new T()));
};
}
IStateTransit* TransitFactory::GetStateTransit(const string& type) const
{
return transits.find(type)->second;
};
private:
map<string, IStateTransit*> transits;
}
Now the problem is (probably obviously) that whenever a user requests a transit by calling GetStateTransit the system currently keeps returning the same object - a pointer to the same object that is. I want to change this.
PROBLEM: How can I return a new (clone) of the original IStateTransit object without the user having to define their own copy constructor or virtual constructor. Ideally I would somehow like the GetStateTransit method to be able to cast the IStateTransit object down to the derived type it is at runtime and return a clone of that instance. The biggest hurdle is that I do not want the user to have to implement any extra (and probably complex) methods.
4 hours of Googling and trying has led me nowhere. The one who has the answer is a hero!
The problem is that you don't have the type information to perform the clone as you only have a pointer to base class type and no knowledge as to what derived types have been implemented and are available.
I think there's a reason that 4 hours of googling haven't turned anything up. If you want IStateTransit to be cloneable you have to have an interface where the derived class implementer provides some sort of clone method implementation.
I'm sorry if this isn't what you wanted to hear.
However, implementing a clone method shouldn't be a big burden. Only the class implementor knows how a class can be copied, given a correct copy constructor, clone can be implemented for a leaf-node class like this:
Base* clone() const
{
return new MyType(*this);
}
You could even macro-alize it; although I wouldn't.
If I understand the problem correctly, you shouldn't insert new T -s into the map, but rather objects that create new T-s.
struct ICreateTransit
{
virtual ~ICreateTransit() {}
virtual IStateTransite* create() const = 0;
};
template <class T>
struct CreateTransit: public ICreateTransit
{
virtual IStateTransit* create() const { return new T(); }
};
And now insert:
transits.insert(pair<string, ICreateTransit*>(name, new CreateTransit<T>()));
And retrieve "copies" with:
return transits.find(type)->second->create(); //hopefully with error handling
It shouldn't be impossible to modify StateTransit<T> so it holds a T of which to make copies of, should the default one not do.
I think the general name for techniques like this is called "type erasure" (derived types "remember" particular types, although the base class is unaware of those).
This problem to me sounds that the abstract factory pattern might be of help. Using this pattern the libraries client can define how your framework builds its types. The client can inject his own subclass of the factory into the framework and define there what types should be build.
What you need is (additionaly)
A base class for the factory
As a client: Derive a concrete factory
A way to inject (as a client) a subtype of the factory into the framework
Call the factory metods to create new types.
Does this help you?