Reputation: 1235
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() ?
Upvotes: 1
Views: 123
Reputation: 10564
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:
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.Upvotes: 0
Reputation: 409166
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
.
Upvotes: 1
Reputation: 258588
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
.
Upvotes: 0