I feel like the answer to this question is really simple, but I really am having trouble finding it. So here goes:
Suppose you have the following classes:
class Base;
class Child : public Base;
class Displayer
{
public:
Displayer(Base* element);
Displayer(Child* element);
}
Additionally, I have a Base* object which might point to either an instance of the class Base or an instance of the class Child.
Now I want to create a Displayer based on the element pointed to by object, however, I want to pick the right version of the constructor. As I currently have it, this would accomplish just that (I am being a bit fuzzy with my C++ here, but I think this the clearest way)
object->createDisplayer();
virtual void Base::createDisplayer()
{
new Displayer(this);
}
virtual void Child::createDisplayer()
{
new Displayer(this);
}
This works, however, there is a problem with this:
Base and Child are part of the application system, while Displayer is part of the GUI system. I want to build the GUI system independently of the Application system, so that it is easy to replace the GUI. This means that Base and Child should not know about Displayer. However, I do not know how I can achieve this without letting the Application classes know about the GUI.
Am I missing something very obvious or am I trying something that is not possible?
Edit: I missed a part of the problem in my original question. This is all happening quite deep in the GUI code, providing functionality that is unique to this one GUI. This means that I want the Base and Child classes not to know about the call at all – not just hide from them to what the call is
It seems a classic scenario for double dispatch. The only way to avoid the double dispatch is switching over types (
if( typeid(*object) == typeid(base) ) ...) which you should avoid.What you can do is to make the callback mechanism generic, so that the application doesn’t have to know of the GUI:
You could then use this machinery like this:
You will have to have one
app_callback::call()function for each class in the hierarchy and you will have to add one to each callback every time you add a class to the hierarchy.Since in your case calling with just a
base&is possible, too, the compiler won’t throw an error when you forget to overload one of these functions in a callback class. It will simply call the one taking abase&. That’s bad.If you want, you could move the identical code of
call_me_back()for each class into a privately inherited class template using the CRTP. But if you just have half a dozen classes it doesn’t really add all that much clarity and it requires readers to understand the CRTP.