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();
Related
Sorry if the question title makes no sense, but I'm not sure how to succinctly describe the problem I'm trying to solve. Here's the issue:
I'm working with a C++ library that makes heavy use of a class which we'll call Base
This library has several different child classes that inherit from Base. We'll call these classes Child1, Child2, .. etc.
This library allows the user create their own child classes of Base and have the library use instances of those classes. I currently have something like this:
class Custom : public Child1 // inherit from Child1, which inherits from Base
{
public:
// override virtual functions here
// ...
void doSomething(); // Utility function I created
}
and then the library I'm using will have some function like this:
void foo(Base* base);
I can pass in a pointer to my Custom class no problem, everything's fine. There are also times where I might need to receive a pointer to a Base object from the library and do stuff with it. That looks something like this:
// code...
Base *base = getSomeBase(); // getSomeBase() is a function from the library that returns a Base*
Custom* myCustom = static_cast<Custom*>(base); // I always make the library use my `Custom` class, so this is safe.
myCustom->doSomething();
This also works without issue. I'm able to invoke my custom doSomething() method by performing a static_cast. However...I now have the need to have more than one possible Custom class. Specifically, I need make the appropriate "child" class to inherit from a template parameter in my Custom class. My code now looks like this:
template <class Child_t>
class Custom : public Child_t // inherit from Child_t, which inherits from Base
{
public:
// override virtual functions here
// ...
void doSomething(); // Utility function I created
}
There is no issue in making the library use my new templated Custom<> class because as long as the template parameter Child_t is in fact one of the library's child classes that inherit from Base, my Custom<> class can simply be cast to a Base*. The issue arises when trying to go in the other direction:
Base *base = getSomeBase();
/* ?????
Would like to call base->doSomething();
But I have no idea which Custom class I have received here. "base" could be
a Child1*, Child2*, etc. There's no way for me to perform a cast.
*/
I am stuck. Note that my function doSomething() will have identical behavior regardless of which Custom<> class I have received from the library. My initial thought was to move my doSomething() function to an interface class.
class Interface
{
public:
virtual void doSomething() = 0;
}
And then have each Custom<> class implement the interface like so:
template <class Child_t>
class Custom : public Child_t, public Interface
{
void doSomething() override;
}
This ends up being unhelpful, as the compiler will not allow me to do the following:
Base *base = getSomeBase();
Interface* interface = static_cast<Interface*>(base); // Error: can't static_cast between unrelated types.
interface->doSomething();
The compiler says that Interface and Base are unrelated types. I know for a fact that any Base* I receive is actually an Interface*, but the compiler can't know that and, I'm guessing, cannot perform the correct pointer adjustment to convert the Base* to an Interface*. At this point I'm stuck and am not sure what to do. I need to call my doSomething() function on whatever Base* I get from the library, but I have no idea which custom child class I'm actually getting. The only solution I currently see is to exhaustively dynamic_cast to every possible child class.
Base *base = getSomeBase(); // getSomeBase()
if (auto* c1 = dynamic_cast<Custom<Child1>*>(base))
{
c1->doSomething();
}
else if (auto* c2 = dynamic_cast<Custom<Child2>*>(base))
{
c2->doSomething();
}
This is an ugly solution. It also places extra cognitive load on the developer because if at any point they decide they need to use a Custom<Child3>, Custom<Child4>, Custom<Child5>, etc. class, they must remember to go back and update the if-else chain to exhaustively check for each possible case. So my question is:
Is it possible to somehow invoke my doSomething() function on the Base* object without actually knowing which Custom<> class I have at compile time, and without simply trying every possible dynamic_cast? Hence the title of my question: can I somehow cast a Base* to an Interface*, given that I know for a fact that they share a common child class (I just don't know which child class).
Am I going about this in the completely wrong way?
you should use dynamic_cast<Interface*>(base)
struct B{virtual ~B(){}};
struct I{virtual int foo()=0;};
struct X:B{};
struct Y:I,X{virtual int foo(){return 10;}};
struct Z:I,X{virtual int foo(){return 20;}};
int main(){
B* x = new Z;
I* i = dynamic_cast<I*>(x);
return i->foo();
}
http://coliru.stacked-crooked.com/a/f7a5787cb9fe80be
I have the following class definitions:
class BaseHandle { /* Lots of things */ };
class VertexHandle : public BaseHandle {
/* Only static members and non-virtual functions, default dtor */ };
class EdgeHandle : public BaseHandle { /* Dito */ };
class FaceHandle : public BaseHandle { /* Dito */ };
All classes have no virtual functions or bases.
The derived classes only derive from BaseHandle and do not add any non-static members, nor non-default dtors.
I want to save Vertex-, Edge- and FaceHandles in the same vector:
std::vector<BaseHandle*> handles;
But it doesn't work, if I retrieve the BaseHandle object and want to dynamic_cast them to the derived object it fails, because the classes are not polymorphic (that's my explanation perhaps I'm wrong).
How could I achieve a common vector of BaseHandles? I should mention, that I can't change the class defintions because they are part of a third party library.
You need to have a virtual destructor in your parent class for it to be used polymorphically
class BaseHandle
{
public:
virtual ~BaseHandle();
...
};
That's because dynamic_cast works with the RTTI (RunTime Type Information) which is only available if your class has at least one virtual member function
And this will also prevent resource leaks, otherwise only the parent class part of your instance would be destroyed
Workaround
You can use an std::vector of std::shared_ptr, not only will you avoid memory leaks by not having to call new and delete by hand but that smart pointer also has a magic property (it stores the deleter to call on destruction based on the way it was constructed) that solves your problem:
int main()
{
std::vector<std::shared_ptr<BaseHandle>> shared_vec;
shared_vec.push_back(std::make_shared<VertexHandle>());
} // At the end of scope all destructors are called correctly
If you don't have access to c++11 you could use boost::shared_ptr
You could store
struct thing
{
enum Type { vertex, edge, face };
Type type;
union
{
VertexHandle * vh;
EdgeHandle * eh;
FaceHandle * fh;
};
};
but it's basically a mess ... are you sure you want to do this? It looks like you are storing multiple types in a single array despite the fact that there is no way to use them polymorphically, so is there actually a good reason to have only one array, and not three?
Following on from a comment by Kerrek. You could "create your own, parallel class hierarchy and add each of those types as a member". For example:
class MyBaseHandle {
public:
virtual ~MyBaseHandle(){}
virtual Box getBoundingBox() const = 0;
};
class MyEdgeHandle : public MyBaseHandle {
std::unique_ptr<EdgeHandle> handle_;
public:
MyHandle(std::unique_ptr<EdgeHandle> handle) : handle_(std::move(handle)) {}
Box getBoundingBox() const override;
};
Then you can dynamic_cast if you want to. But I would try and avoid using dynamic_cast at all. Add virtual methods in your parallel class hierarchy that do what you need. For example I've added a virtual getBoundingBox function to the base class that you can then specialize for your particular kinds of handle:
Box MyEdgeHandle::getBoundingBox() const {
// Get data from EdgeHandle
auto v1 = handle_->getVertex1();
auto v2 = handle_->getVertex2();
// create box from edge data...
return box;
}
Live demo
If all classes derived from BaseHandle only use single-inheritance from BaseHandle (plus maybe inheritance from empty classes with trivial dtor, which are subject to empty-baseclass-optimization) and don't add anything but non-virtual functions and static members, and all derived classes use the default dtor or equivalent, you can just static_cast to the target.
Though be aware that there is no way to know which of the derived classes, if any, it actually was.
I have a function like this:
void something(void *obj)
{
obj->Set();
}
The compiler says that left of the dereference operator has to be a pointer to a class/struct/union/generic (translated from german not sure about wording).
The idea is that I want to call the something function of obj no matter what is passed to something. It is ensured that it has this function. How can i achieve that?
--EDIT--
I started to work on an existing Software which has like > 100 Classes for datatypes. In one part of the code there is a big switch statement which depending on an id creates an instance of one of these classes and calls the Set function for that one. Now i want to do multiple of these calls parallel, and because of this i want to bring the ->Set() call to a seperate function which i then can call in a new thread. Sadly there is no baseclass and i cant change too much in the "big picture". What is the best way to do this?
C++ doesn’t allow this (for good reasons: even if you can ensure that the object always has a function, C++ cannot, and since you can make mistakes, C++ is justified in distrusting you).
The proper way to do this is to have a common base class which defined this method for all types that you want to use here, and then use this common base class as the argument of this function.
Alternatively, if it’s known at compile time which type is used here, then the appropriate implementation uses templates:
template <typename T>
void f(T const& obj) {
obj.something();
}
Whatever you do, void* is not appropriate. There are very rare legitimate use-cases for it in C++.
You need a base class or interface for whatever is passed into doSth:
class Base
{
public:
virtual void something() = 0; //override this in derived classes
}
doSth(Base* obj)
{
obj->something();
}
You can also cast the void* back to the original type:
doSth(void* obj)
{
((Base*)obj)->something();
}
but passing a void* as parameter suggests a faulty design. What exactly are you trying to achieve?
You need to implement pure virtual Base class with this function:
class Base
{
public:
virtual ~Base(){}
virtual void somefunction()=0;
}
class Derived1: public Base
{
public:
void somefunction()
{
//do something
}
}
class Derived2: public Base
{
public:
void somefunction()
{
//do something
}
}
And than use dynmic cast to get Base* from void*
doSth(void *obj)
{
Base *bobj=dynamic_cast<Base*>(obj);
if ( bobj )
bobj->somefunction();
}
Or mor simplier:
doSth(Base *obj)
{
obj->somefunction();
}
And usage is like:
Base *p1 = new Derived1();
Base *p2 = new Derived2();
doSth(p1); // cals somefunction in Derived1 class
doSth(p2); // cals somefunction in Derived2 class
The doSth method could take a function pointer as a parameter.
doSth( (*someFunc)() ) {
obj->*someFunc();
}
The call would look like:
doSth( &function );
When passing function pointers between different classes you should create a typedef for each function pointer and use qualifiers for each function identifier.
Just define an interface that lists all the functions of all the objects that you want to reference by the pointer, but the type of this pointer should not be void, but the name of this interface instead.
Then you will be able to call every function of every object that you want by this pointer, but make sure that all structures and classes of the objects implement all the functions of the interface!
This is also important to write the : public and then the name of the interface in the header of every structure and class!
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.
Building a GUI system and I have a few classes for different GUI components that derive from a base "GUIcontrol" class. What I want is to have just one function to return any type of component but be able to work with the functions specific to that component type (functions of the derived class). I noticed that the polymorphism approach is going to become a problem I have to declare all the derived functions in the base which is unnecessary for this, since I will never create an object just from the base class.
class GUIcontrol {
protected:
std::string _name;
// these two methods (along with name()) will be used by all types
virtual void position(/*parameters*/)
virtual void useImage(/*parameters*/)
// these should be only in derived types
virtual void setHotSpot(/*parameters*/);
virtual void setScrollButtons(/*parameters*/);
public:
std::string name();
/*etc*/
}
class GUIbutton : public GUIcontrol {
public:
void setHotSpot(/*parameters*/);
}
class GUIscrollBar : public GUIcontrol {
public:
void setScrollButtons(/*parameters*/);
}
GUIcontrol* GUIsystem::getControl(std::string name);
The problem with this is that if I want to add more functions unique to GUIbutton or GUIscrollBar, or any functions to other derived GUI classes, I also have to declare them virtual in the base class so the compiler doesn't complain about something like "setHotSpot" not being a member of the base class it returns.
The base class does have member functions that will apply to all the derived classes, such as telling the object where it should be positioned, what image it needs to use, what it should be called, etc. But I don't want to keep stuffing the base class with other functions that need to stay exclusive to certain derived classes.
As I keep adding more virtual functions I would end up with a huge blob object for the base class. Can I design this in a cleaner way? Note that I am still not sure if I want to use static_cast/dynamic_cast for getControl() to solve this but just want to know if there are any other ways around this to clean it up.
The base class should only contain methods for functionality common to all controls.
If you're going to use functionality that only makes sense for one type of control, you should be checking that the control is of the correct type anyway, and can then cast it to that type.
The base class is exclusively common functionality. If you want your method to behave differently for different controls, use dynamic_cast. If you want it to act the same for all controls, use a virtual method.
This is your problem:
What I want is to have just one
function to return any type of
component but be able to work with the
functions specific to that component
type (functions of the derived class).
What you want is to treat them the same but differently. Huh. I wonder how you're going to make that work. You need to decide if you want to treat them all the same, or if you want to treat them differently.
Type checking and then downcasting isn't the right way to do this. What you should be doing is placing generic methods onto your base class which perform the types of operations you want, and then overriding them in subclasses. For example, if you want the GUIControl to be able to draw itself, then put a doDraw() method on the base class, then override that in each subclass to do as is needed. If you instead put a getTitleBar(), getText() etc. methods on your subclass, then have the caller downcast and calls those specific methods depending on the type, your encapsulation is broken. If you have some common code that multiple subclasses need to do their drawing, then you factor this out either through another parent class, or through composition. Using dynamic_cast, or putting specific methods on the generic subclass, will likely make your code worse.
If I have this right: You want to be able to pass around base class objects but have a clean way to call specific derived class methods where the derived class implements those methods?
Sounds like the 'mixin' pattern might help:
struct Base
{
virtual ~Base() {}
};
struct Mixin
{
virtual ~Mixin() {}
virtual void mixedMethod() = 0;
};
struct Concrete : Base, Mixin
{
virtual void mixedMethod() { std::cout << "Mixing" << std:: endl; }
};
Base* create() { return new Concrete;}
bool mixIt(Base& b)
{
Mixin* m = dynamic_cast<Mixin*>(&b);
if (m)
m->mixedMethod();
return m;
}
void test ()
{
Base* b = create();
assert(mixIt(*b));
Base base;
assert(!mixIt(base));
}
[ Yes, real code never uses struct for polymorhic classes; just keeping it compact.]
The idea here is that the availability of a given method is encapsulated in the Mixin class, which is an pure abstract base class, possibly with only a single pure virtual function.
If you want "know" your base class object is of the derived type, you can call the mixin classes method. You can wrap the test and the call in a non-member function; this allows you to keep the base calss interface itself clean.