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.
Related
Let's say I have an abstract base class that has two derived classes. Each of those derived classes has some new functionality not present in the abstract base class, but both derived classes have the same function. For example:
class MyBase:
public:
/* ... */
virtual void DoSomething() = 0;
/* ... */
class MyAlpha : public MyBase
public:
/* ... */
void DoSomething() { /* does sometihng */ }
/* Function not present in abstract base class */
void DoSomethingNew() { /* does something new */ }
/* ... */
class MyBeta : public MyBase
public:
/* ... */
void DoSomething() { /* does sometihng */ }
/* Function not present in abstract base class */
void DoSomethingNew() { /* does something new */ }
/* ... */
Now I have a templated function somewhere that accepts a pointer (in my case a std::unique_ptr) to the base class, and I want to be able to call the DoSomethingNew() function (the function that is present in both derived classes but not the base class. For example:
template <typename Base_t> void MyOperation(std::unique_ptr<Base_t> &base_object) {
/* some ops */
base_object->DoSomethingNew();
}
How do I go about doing this? I feel like template specialization might be the way to go here but I'm not quite sure. I am working on extending an open source library with a new feature, so I have limitation on what existing code I can/should modify to make my feature work. The base class in my actual use case is code that I'd like to avoid modifying, but for general use in this library, my function signature needs to accept a pointer to the base class.
As the base class is virtual, the actual usage is something like:
std::unique_ptr<MyBase> object = std::unique_ptr<MyAlpha>(new MyAlpha);
MyOperation(object);
How do I go about this using derived class functionality in the MyOperation() function? If it makes a difference, I have to stay C++11 compatible.
Each of those derived classes has some new functionality not present in the abstract base class, but both derived classes have the same function.
Then capture that in a possibly abstract intermediate class:
class MyMiddle : public MyBase {
public:
virtual void DoSomethingNew() = 0;
};
class MyAlpha : public MyMiddle {
public:
void DoSomething() override;
void DoSomethingNew() override;
};
class MyBeta : public MyMiddle {
public:
void DoSomething() override;
void DoSomethingNew() override;
};
This way you can implement the common functionality around DoSomethingNew by referencing MyMiddle, avoiding a lot of code duplication you might otherwise get.
Now I have a templated function somewhere that accepts a pointer (in my case a std::unique_ptr) to the base class, and I want to be able to call the DoSomethingNew() function.
Since you only have a pointer to the base class, the compiler will not out of the box allow you to call methods of a derived class on that. However, if you expect the implementation to actually be an instance of a derived class, you can cast to that.
Use a dynamic_cast to check whether the derived class is of the expected type and use it as that type if it is. Use a static_cast if you are 100% totally absolutely sure that the argument will always be of the derived class, now and forever in the future. In other words, don't. Go for dynamic_cast.
Note that dynamic_cast is available for raw pointers but not for unique_ptr. So you have two options: either keep the unique pointer to base and use a raw pointer to derived for access. Or cast the pointer in an elaborate multi-step procedure. The latter only makes sense if you want to hold on to the pointer for longer in a context where it needs to be of the derived type. The simple case goes like this:
void SomethingSimple(std::unique_ptr<MyBase> base) {
MyMiddle* derived = dynamic_cast<MyMiddle>(base.get());
if (derived == nullptr) {
// derived wasn't of the correct type, recover in a reasonable way.
return;
}
derived->DoSomethingNew();
}
The more complex pointer cast goes like this instead:
void SomethingComplicated(std::unique_ptr<MyBase> base) {
MyMiddle* derived = dynamic_cast<MyMiddle>(base.get());
if (derived == nullptr) {
// derived wasn't of the correct type, recover in a reasonable way.
return;
}
std::unique_ptr<MyMiddle> middle(derived);
// Here two unique_ptr own the same object, make sure not to throw exceptions!
base.release(); // Complete transfer of ownership.
SomethingThatNeedsTheNewFunction(middle); // Pass ownership of middle type.
}
Of course, std::unique_ptr does allow for custom deleters, which makes this whole setup way more fun. I recommend you read this answer for code that is propagating the deleter while constructing a unique pointer to a derived class. This only becomes necessary if your function signature allows for a non-standard deleter in its pointer argument.
You could do the above without the MyMiddle class, using two separate calls to dynamic_cast to try converting to each of your derived classes in turn. But as long as the middle class and the shared functionality makes sense conceptually I'd go for that. If you did two separate casts, then you could call a template function for both cases, and that template function could assume existence of that function even though it would be operating on different argument types. Doesn't feel like a great solution to me, though.
I feel like template specialization might be the way to go here but I'm not quite sure.
That would work if the caller would call the function with the actual derived type as the static type of the argument. So you could do
template <typename Base_t> void MyOperation(std::unique_ptr<Base_t> &base_object) {
// Handle the case where DoSomethingNew is not an option.
}
template <> void MyOperation(std::unique_ptr<MyAlpha> &alpha_object) {
alpha_object->DoSomethingNew();
}
template <> void MyOperation(std::unique_ptr<MyBeta> &beta_object) {
beta_object->DoSomethingNew();
}
But the following would still not call the specialized function:
std::unique_ptr<MyBase> object(new MyAlpha());
MyOperation(object);
Even though object dynamically contains a MyAlpha its static type is a unique pointer to MyBase, and that's what drives the template parameters. So I can't see a way where such a specialization would be useful to you.
dynamic_cast<> exists for when you need to either down cast or cross cast from your pointer-to-base into a derived class. In your example it would look something like this:
std::unique_ptr<MyBase> object = std::unique_ptr<MyAlpha>(new MyAlpha);
// ...
dynamic_cast<MyAlpha*>(object.get())->DoSomethingNew();
You can read more about it here, but as I mentioned in my comment, too many of these is an indicator you have a design problem. Especially here when you have that functionality in both derived classes, it could easily be moved into the base class.
As an alternative to dynamic_cast<> since you are unable to modify the base class, you could create your own base class where you inherit from the unmodifiable base class and customize the interface to something you will actually use.
class NewBase : public MyBase
{
public:
void DoSomething() = 0;
void DoSomethingNew() = 0;
};
std::unique_ptr<NewBase> object = std::unique_ptr<MyAlpha>(new MyAlpha);
// ...
object->DoSomethingNew();
I've written what I would hoped to be a general purpose CRTP class that allows my own classes to easily extend a class that implements a shared_from_this function (presumably returning a shared pointer equivalent to this), giving direct access to the shared pointer for the derived class instead of the base, as follows:
template<class Self, class Super>
class inherit_shared_from_this : public Super {
public:
std::shared_ptr<const Self> shared_from_this() const {
return std::static_pointer_cast<const Self>(Super::shared_from_this());
}
std::shared_ptr<Self> shared_from_this() {
return std::static_pointer_cast<Self>(Super::shared_from_this());
}
};
This works quite well for single inheritance trees, but I was wanting to extend it to be able to inherit from more than one class that implements shared_from_this. When I do so, however, I get an error 'shared_from_this' is ambiguous, because the compiler can't tell which exact class I am meaning to inherit the shared_from_this function. In fact, it does not matter which one.
What I wanted to do is define a class as follows:
class Foo : public inherit_shared_from_this<Foo, A, B, C> {
...
};
Where all of A, B, C, and D implement a shared_from_this function, and this class will publicly inherit from each of the classes other than the first, and implement exactly two shared_from_this methods, for both const and non-const versions, to return the applicable shared_pointer version of this (in this case, std::shared_ptr<Foo>).
The first thing I tried to do was adding a variadic definition for the class as follows:
template<class Self, class Super, typename... Args>
class inherit_shared_from_this : public Super, public inherit_shared_from_this<Self, Args...> {
public:
std::shared_ptr<const Self> shared_from_this() const {
return std::static_pointer_cast<const Self>(Super::shared_from_this());
}
std::shared_ptr<Self> shared_from_this() {
return std::static_pointer_cast<Self>(Super::shared_from_this());
}
};
That did not work, however... it objected that the two definitions of inherit_shared_from_this had different numbers of parameters.
Any ideas on how I can do what I am trying to accomplish, or is it just not possible?
EDIT:
A clarification on why std::shared_from_this is not usable as-is:
If I simply inherit directly from the class that inherited std::enable_shared_from_this in a derived class that also inherits from something that inherited from std::enable_shared_from_this, then it returns the wrong pointer type. If I use multiple inheritance and also inherit from std::enable_shared_from_this in a derived class whose base had extended std::enable_shared_from_this, then calling shared_from_this() in the derived class is ambiguous. Therefore a class that can inherit from such classes is required if access to the derived pointer is wanted.
EDIT:
This question differs from mine in that I am wanting to avoid adding virtual inheritance into things unless it is explicitly asked for. Since std::enable_shared_from_this itself does not have a virtual destructor in the first place, it seems improper to add that cost to what I am trying to design as a general purpose class whose purpose is to be just as reusable.
Let's say we have:
class Base {...}
class A : public Base {...}
class B : public Base {...}
Is it possible to set as argument type of a generic method:
myMethod([typei'mlookingfor] c) {}
so that I can pass Base, A and B to myMethod() without overloading the method?
and also make it work with references and pointers?
If a pointer or a reference to the base class works for you, just use that:
void myMethod(Base& c) {}
A a;
B b;
myMethod(a); //OK
myMethod(b); //OK
Note that you'll have to use references or pointers to prevent object slicing. If the method is myMethod(Base c), you'll lose type information of derived objects.
If not, you can use a template
template<typename T>
void myMethod(T& c)
{
}
A a;
B b;
myMethod(a);
myMethod(b);
Q: Is it possible to define the type of a method argument to be a class or any derivate class?
A: Sure. Why not?
If you want a "generic" parameter that can be any arbitrary type, just use a template.
Otherwise, if you want "class or any subclass", just use the base class.
Useful quote:
http://wiki.answers.com/Q/What_are_the_concepts_of_object_oriented_programming
Polymorphism allows the programmer to treat derived class members just
like their parent class' members. More precisely, Polymorphism in
object-oriented programming is the ability of objects belonging to
different data types to respond to method calls of methods of the same
name, each one according to an appropriate type-specific behavior.
Which, I believe, is exactly what you're looking for :)
There are 2 ways how to do this. 1st is dynamic polymorphism. Works only with pointers and refs. There is small run time overhead:
void myMethod(Base& x) { ...}
2nd - static polymofism:
template<class T>
std::enable_if<is_base_of<Base,T>::value>
myMethod(base x) {...}
I was not really sure how to formulate my question, but here is the puzzle I am trying to resolve:
if (config.a)
myObject = new Object<DummyInterface>();
else
myObject = new Object<RealInterface>();
so the task is to create a object with a dummy interface if it is specified in config, otherwise use real interface class.
How do I declare myObject then?
there are couple options, I could have Object class to derive from abstract class without templates: i.e.:
class Base
{
...
}
template <class T>
class Object : public Base
{
...
}
Then I could declare myObject as:
Base* myObject;
But here is the problem: what if my Object class declares a non virtual method:
template <class T>
class Object : public Base
{
public:
T getInterface() { return myInterface;}
private:
T myInterface;
}
I cannot call it like this:
myObject->getInterface()
and I cannot do dynamic cast, because I don't know the type until the runtime...
Any suggestions how to get around it? Maybe there is a another solution?
One way around is to use the visitor pattern. This way, your base class may implement a visit() method and your derived instances can override...
For example..
SomeComponent
{
template <typename T> // I'm being lazy here, but you should handle specific types
void handle(T& cInst)
{
// do something
}
};
class Base
{
public:
virtual void visit(SomeComponent& cComp) = 0;
};
template <class T>
class Object : public Base
{
public:
virtual void visit(SomeComponent& cComp)
{
cComp.handle(*this);
}
};
Now you can do this
SomeComponent c;
Base* obj = new Object<int>;
obj->visit(c);
And c will get the correct type.
if (config.a)
myObject = new Object<DummyInterface>();
else
myObject = new Object<RealInterface>();
This construction is incorrect in terms of the polymorphism.
Two template instantiations are two different classes. The best situation is when you have something like that:
template <class T> SomeClass: public SomeBaseClass
{
};
.........
SomeBaseClass* myObject;
But it brings you no profit.
The simplest and right solution is the virtual functions. The visitor pattern seems useful too.
I actually think that the visitor pattern would be misused here. Instead, this is a classic switch-on-types code smell that is best handled by polymorphism.
When you say "what if one derived class has an additional method to call", that is assuming a specific design. That is not a functional requirement. A functional requirement would be "what if one of the two objects created had to do behavior X during event Y". Why is this different? Because there are a number of ways to implement this that don't require more interface (though maybe more methods).
Let me show an example.
You have your factory
std::map<ConfigValue, Generator> objectFactory_;
That you've registered a bunch of generators for (probably in constructor of class)
RegisterGenerator(configValueA, DummyGenerator);
RegisterGenerator(configValueB, RealGenerator);
...
And at some point you want to create one of those objects.
shared_ptr<Base> GetConfigObject(ConfigFile config)
{
return objectFactory_[config.a]();
}
And then you want to use the object for handling an event, you can do
void ManagingClass::HandleEventA()
{
theBaseObjectReturned->HandleEventAThroughInterfaceObject(this);
}
Note how I passed a this pointer. This means if you have one object that doesn't want to do anything (like make that extra behavior call) that your managing class may provide, it doesn't need to use this.
Object<DummyInterface>::HandleEventAThroughInterfaceObject(ManagingClass *)
{
// just do dummy behavior
}
And then if you want to do something extra (call a new behavior) it can do it through that pointer in the RealInterface
Object<RealInterface>::HandleEventAThroughInterfaceObject(ManagingClass * that)
{
that->DoExtraBehavior();
// then dummy - or whatever order
// you could even call multiple methods as needed
}
That's the basic approach you should always take when dealing with polymorphism. You should never have two different code paths for different types except through calls to virtual dispatch. You should never have two different code blocks, one that calls methods A, B, and C and another that only calls A and D when dealing with a base object, depending on type. Instead, always make the derived objects do the work of figuring out what to do - because they know who they are. If you need to do stuff in the managing object, pass a this pointer for them to work with.
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.