Is my diamond inheritance compiler error impossible to solve? - c++

Structure
I have created a diamond inheritance problem. It looks like this
I thought I understood virtual inheritance fairly well, however I now think that I have slightly missunderstood it.
It was my understanding that virtual inheritance tells the compiler to ignore any member data or functions which appear twice with the same name as a result of a diamond inheritance pattern, thus only the "non virtual" inherited components would be contained in the derived class.
However I now think this understanding of how the compiler implements inheritance is wrong.
I have 2 diamond inheritance patterns in my inheritance hierarchy. They are marked using the notes included.
I have also added some notes to show where I attempted to put virtual to resolve the compiler errors, but a different compiler error resulted. The note briefly describes what the problem was. (See the final section of this question if you are interested)
Useage
The intended usage is a std::list<GUIObject*> is created. All gui objects should be able to Draw and ProcessEvent. Not all gui objects will contain the container contained inside SingleLineBuffer.
Buffer and FileBuffer inherit from SingleLineBuffer to change how the container inside SingleLineBuffer behaves. (FileBuffer actually only added new file IO functions.)
One could create an instance of one of the buffers, however I don't in the context I am working with.
One cannot create an instance of any of the abstract GUI* classes. Thinking about it, there should probably be an additional abstract base class below GUIMultilineTextEntry which inherits from FileBuffer.
The actual objects that the user may create an instance of are Label, Inputbox and Textbox. I intend to add more in the future, such as a multiline label. This would have to inherit from a base class which inherited from Buffer and GUITextObject, probably.
This inheritance structure quickly became quite complicated. I wrote it as I went along, guided by what my code was instructing me to do. For example, I wrote a Textbox class, then said "the container in Textbox is essentially the same as the container in Label, therefore they should inherit from a common object". The difference was that a Textbox has file IO, an additional inheritance step is dictated, and a Textbox can contain the new line character in the container, so an additional inheritance step is dictated here too.
Questions
Can this inheritance problem be resolved?
Which classes should inherit virtually from which other classes.
My attempts
No virtual inheritance
Compiler error: (multiple versions of)
error: request for member ‘Size’ is ambiguous
status_text << "Save: " << static_cast<Textbox*>(current_window._guiobject_map_.at("textbox"))->GetFilename() << ", " << static_cast<Textbox*>(current_window._guiobject_map_.at("textbox"))->Size() << " bytes";
Size is defined in SingleLineBuffer. It is a non-virtual function, as the container exists only in SingleLineBuffer, and therefore Size is written to work correctly for both Buffer and FileBuffer.
Break diamond 1: Put virtual between GUITextObject and GUITextEntry to stop Size being "pulled down via GUITextObject" before it is overridded in Buffer. (Blue mark)
Compiler error (1):
error: no matching function for call to ‘GUITextObject::GUITextObject()’
I can fix this by calling the required constructor from GUIMultilineTextEntry. I don't understand why this is needed. (Second Question) Fix shown below:
GUIMultilineTextEntry(const FontTextureManager& ftm, const int width, const int height)
: GUITextEntry(ftm, width, height)
, GUITextObject(ftm, width, height) // also call the constructor for the class which was inherited virtual in the previous step
{ ...
This same fix is needed in Inputbox and Textbox.
However this results in a further error
error: cannot convert from pointer to base class ‘GUIObject’ to pointer to derived class ‘Textbox’ via virtual base ‘GUITextObject’
static_cast<Textbox*>(current_window._guiobject_map_.at("textbox"))->SetFilename(filename);
I believe I could resolve this by using dynamic_cast instead of static_cast, however I am not sure this is a good idea as I have heard that dynamic casting can slow down code significantly.
Break diamond 1, second attempt:
I made a second attempt at resolving the problem by inheriting virtually between Buffer and SingleLineBuffer. (See red dot) However when I did this the compiler error changed to
error: no unique final overrider for ‘virtual void SingleLineBuffer::SetText(const string&)’ in ‘Textbox’
My guess is this is equivalent to the compiler telling me "you overrided some functions in Buffer by inheriting, but you inherited virtually, and the functions you have overridden are also present in a derived class via non-virtual inheritance, so I don't know which one should take precidence" - but this really is a guess.
I tried similar things to break diamond 2 but encountered similar compiler errors.
Since this is now quite a long question, I will not list all the details of that attempt here.

The answer to the titular question is no. (Normally the MCVE comes in the question, but I guess here it really is an answer.) As for the detailed questions:
An inheritance needs to be virtual if it is directly from the common ancestor (the "top of the diamond") of which you want only one copy in the complete object. (So here, you need 4 virtuals, just by counting converging arrows.)
You need to call the constructor of every virtual base in every concrete class, because the most-derived class initializes them directly.
You really can't use static_cast from (or via, as it says) a virtual base, since the class layout varies between instances (because of differing other base classes). However, the cost of one dynamic_cast per GUI operation is surely immeasurable.
Your "unique final overrider" error analysis is probably right, but the answer is more cowbellvirtual.

Related

Double Dreadful Diamond Inheritance issue (alternative solutions allowed)

I ended up in a situation lined out below.
I have one library that is pure CPP without external libraries, and another project that is an SDK to interface with an external library.
"I" in front of the name indicates an abstract class. Arrows indicate inheritance.
I have IDevice which contains HandleInput(data) as a callback, and StartDevice().
Then I have a more specific type of device: ISmartwatch (containing StartTimer), and from that inherits a more specific version SmartwatchV1, which implements HandleInput(data) according to its needs.
That all seemed great until I came to the external SDK part, where the library expects me to use inheritance to interface with it to override some functions. So, I have to inherit from the external library, and from my own CPP library, to override the functions I need. Most of these library overrides suit any device (IExternalLibDevice), but a few are specific to the exact Stopwatch version (ExternallSmartWatchV1).
Then for polymorphism in my SDK, I would like to call and override functions both provided by the library and my own device example: libDevice.StartDevice() and use library calls within this optionally overriden StartDevice. Or stopWatch.StartTimer(), stopwatchV1.libraryOverride().
The object which I need to create is the green one, however, the white SmartWatchV1 is also an object to instantiate in applications without the library. (And obviously I keep in mind any future alternative devices or stopwatch versions.)
I think if I drop any inheritance arrow, I would either lose out on polymorphism (so SDK code will only work for a very specific smartwatch version), or I cannot override functions I need anymore. Composition would be nice, but won't work for overriding functions, or is there an option I don't know about?
And so, I ended up here. I am encountering quite some annoying errors implementing this, since double diamond is usually solved with virtual inheritance (nice page about double diamond: https://isocpp.org/wiki/faq/multiple-inheritance#mi-diamond). However, when applied here (see the v's that indicate "virtual" in the image), I have one inheritance that should both be virtual and not be virtual. Additionally, virtual inheritance makes constructors really annoying in my generic CPP library. Even without virtual (which as far as I'm aware would cause some duplication of classes in memory and a lot of ambiguity to solve), I have some constructor errors ("no suitable default constructor" for a class that must not have a default constructor, etc) issues.
I have been battling to solve this for a long time, and I hope someone more experienced can make a suggestion that provides a better solution for my code structure or issue.
In the end, I solved it by using composition:
Add an IDevice pointer to IExternalLibDevice that is set in the constructor.
In IExternalLibSmartwatch: add an ISmartwatch pointer to the constructor and pass it to its parent constructor. Also, add a function that retrieves the IDevice pointer as an ISmartwatch.
In ExternalSmartwatchV1: also add a SmartwatchV1 to the constructor and pass it to its parent constructor, and create a function that retrieves the IDevice pointer as a SmartwatchV1.
The IDevice pointer holds the reference to the cppLibDevice, and can now be cast to any of the subclasses it belongs to. Downside: I cannot override the cpp lib classes, but it was not a hard requirement for my code, since I created alternative functions in the ExternalLib classes that can optionally call the cppLibDevice functions, or completely replace them.

Why does C++ constructor accept incorrect type as a parameter?

The title pretty much says it all. I have a constructor
Brain::Synapse::Synapse(Neuron *new_neuron);
But when I pass it an incorrect type (a member from a vector like this)
std::vector<Motor_Neuron*> neurons;
Synapse *new_synapse = new Synapse(neurons[neuron_index]);
It works just fine (and that's the issue). Motor_Neuron is a derived class from Neuron, so I suspect this is why. My problem ultimately is that I need some Synapses to be connected to Neurons and others to Motor_Neurons. The Synapse class has a member that is a pointer to the "connected neuron". I have been trying to overload the constructor, but I don't think that will work, because if one of the constructors accepts the wrong type I don't see how the correct constructor will be selected.
If Motor_Neuron inherits from Neuron, then it isn't an incorrect type. That is the entire basis of inheritance; that inherited classes are their parent classes, just with some extra bits and pieces.
It sounds more like you need to work on your application's class hierarchy. The SOLID principles are great guidelines. The relevant one is the Liskov Substitution Principle which states that “objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.” If your Motor_Neuron cannot fill the role of a Neuron, then it should not inherit from it. If it needs to leverage some functionality from a Neuron, maybe have it have a Neuron as a member and use its functions from there.
There are work arounds with creating a Motor_Neuron constructor and deleting it or throwing an exception, but I don't really condone trying to fix the symptom like that, and instead get to the source; your design.

Is using an empty base class justified in this example?

I'm writing a Window class which propagates different types of events, listed in
enum Event {WINDOW_ClOSE=0x1, WINDOW_REDRAW=0x2, MOUSE_MOVE=0x4, ...};
to objects which have registered for notification with the window. For each type of event, I have an abstract class which any object must extend in order to allow notification. To react to, say, a MOUSE_MOVE event, my object would inherit from MouseMoveListener, which has a process_mouse_move_event() method which is called by Window. Listening to many events can be combined by extending multiple of these classes, which all inherit from the EventListener base class. To register an object, I would call
void Window::register(EventListener* object, int EventTypes)
{
if(EventTypes&WINDOW_CLOSE)
/* dynamic_cast object to WindowCloseListener*, add to internal list of all
WindowCloseListeners if the cast works, else raise error */
if(EventTypes&MOUSE_MOVE)
/* dynamic_cast object to MouseMoveListener*, add to internal list of all
MouseMoveListeners if the cast works, else raise error */
...
}
This works fine, but my gripe is that EventListener is completely empty and that seems code smelly to me. I know I could avoid this by removing EventListener altogether and having a separate Window::register for each type of event, but I feel that this would blow up my interface needlessly (especially since methods other than register might crop up with the same problem). So I guess I am looking for answers that either say:
"You can keep doing it the way you do, because ..." or
"Introduce the separate Window::register methods anyway, because ..." or of course
"You are doing it all wrong, you should ...".
EDIT:
From the link in Igors comment: What I do above only works if there is at least one virtual member in EventListener for example a virtual destructor, so the class is not technically completely empty.
EDIT 2:
I prematurely accepted n.m.'s solution as one of the type "I'm doing it all wrong". However, it is of the second type. Even if I can call EventListener->register(Window&) polymorphically, Window needs to implement a highly redundant interface (in terms of declared methods) that allows EventListeners to register for selective notification. This is equivalent to my alternative solution described above, only with the additional introduction of the EventListener class for no good reason. In conclusion, the canonical answer seems to be:
Don't do dynamic_cast + empty base class just to avoid declaring many similar functions, it will hurt you when maintaining the code later. Write the many functions.
EDIT 3:
I found a solution (using templates) which is satisfactory for me. It does not use an empty base class any more and it does not exhibit the maintenance problem pointed out by n.m.
object->registerWindow (this, EventTypes);
Of course you need to implement registerWindow for all EventListener heirs. Let them check for event types which are relevant to them.
UPDATE
If this means you need to redesign your code, then you need to redesign your code. Why is it so? Because dynamic_cast is not a proper way to do switch-on-types. It is not a proper way because every time you add a class in your hierarchy, you need to go over and possibly update all switches-by-dynamic-cast in your old code. This becomes very messy and unmaintainable very quickly, and this is exactly the reason why virtual functions were invented.
If you do your switch-on-types with virtual functions, every time you change your hierarchy you have to do... nothing. The virtual call mechanism will take care of your changes.
This is what I ended up doing:
template <int EventType> void register_(EventListener<EventType> Listener)
{
// do stuff with Listener, using more templates
};
It turned out that static polymorphism was better suited for my needs - I just wanted to avoid writing
register_mouse_motion_event(...)
register_keyboard_event(...)
and so on. This approach also nicely eliminates the need for an empty base class.

Is there any way to avoid declaring virtual methods when storing (children) pointers?

I have run into an annoying problem lately, and I am not satisfied with my own workaround: I have a program that maintains a vector of pointers to a base class, and I am storing there all kind of children object-pointers. Now, each child class has methods of their own, and the main program may or not may call these methods, depending on the type of object (note though that they all heavily use common methods of the base class, so this justify inheritance).
I have found useful to have an "object identifier" to check the class type (and then either call the method or not), which is already not very beautiful, but this is not the main inconvenience. The main inconvenience is that, if I want to actually be able to call a derived class method using the base class pointer (or even just store the pointer in the pointer array), then one need to declare the derived methods as virtual in the base class.
Make sense from the C++ coding point of view.. but this is not practical in my case (from the development point of view), because I am planning to create many different children classes in different files, perhaps made by different people, and I don't want to tweak/maintain the base class each time, to add virtual methods!
How to do this? Essentially, what I am asking (I guess) is how to implement something like Objective-C NSArrays - if you send a message to an object that does not implement the method, well, nothing happens.
regards
Instead of this:
// variant A: declare everything in the base class
void DoStuff_A(Base* b) {
if (b->TypeId() == DERIVED_1)
b->DoDerived1Stuff();
else if if (b->TypeId() == DERIVED_2)
b->DoDerived12Stuff();
}
or this:
// variant B: declare nothing in the base class
void DoStuff_B(Base* b) {
if (b->TypeId() == DERIVED_1)
(dynamic_cast<Derived1*>(b))->DoDerived1Stuff();
else if if (b->TypeId() == DERIVED_2)
(dynamic_cast<Derived2*>(b))->DoDerived12Stuff();
}
do this:
// variant C: declare the right thing in the base class
b->DoStuff();
Note there's a single virtual function in the base per stuff that has to be done.
If you find yourself in a situation where you are more comfortable with variants A or B then with variant C, stop and rethink your design. You are coupling components too tightly and in the end it will backfire.
I am planning to create many different children classes in different
files, perhaps made by different people, and I don't want to
tweak/maintain the base class each time, to add virtual methods!
You are OK with tweaking DoStuff each time a derived class is added, but tweaking Base is a no-no. May I ask why?
If your design does not fit in either A, B or C pattern, show what you have, for clairvoyance is a rare feat these days.
You can do what you describe in C++, but not using functions. It is, by the way, kind of horrible but I suppose there might be cases in which it's a legitimate approach.
First way of doing this:
Define a function with a signature something like boost::variant parseMessage(std::string, std::vector<boost::variant>); and perhaps a string of convenience functions with common signatures on the base class and include a message lookup table on the base class which takes functors. In each class constructor add its messages to the message table and the parseMessage function then parcels off each message to the right function on the class.
It's ugly and slow but it should work.
Second way of doing this:
Define the virtual functions further down the hierarchy so if you want to add int foo(bar*); you first add a class that defines it as virtual and then ensure every class that wants to define int foo(bar*); inherit from it. You can then use dynamic_cast to ensure that the pointer you are looking at inherits from this class before trying to call int foo(bar*);. Possible these interface adding classes could be pure virtual so they can be mixed in to various points using multiple inheritance, but that may have its own problems.
This is less flexible than the first way and requires the classes that implement a function to be linked to each other. Oh, and it's still ugly.
But mostly I suggest you try and write C++ code like C++ code not Objective-C code.
This can be solved by adding some sort of introspection capabilities and meta object system. This talk Metadata and reflection in C++ — Jeff Tucker demonstrates how to do this using c++'s template meta programming.
If you don't want to go to the trouble of implementing one yourself, then it would be easier to use an existing one such as Qt's meta object system. Note that this solution does not work with multiple inheritance due to limitations in the meta object compiler: QObject Multiple Inheritance.
With that installed, you can query for the presence of methods and call them. This is quite tedious to do by hand, so the easiest way to call such a methods is using the signal and slot mechanism.
There is also GObject which is quite simmilar and there are others.
If you are planning to create many different children classes in different files, perhaps made by different people, and also I would guess you don't want to change your main code for every child class. Then I think what you need to do in your base class is to define several (not to many) virtual functions (with empty implementation) BUT those functions should be used to mark a time in the logic where they are called like "AfterInseart" or "BeforeSorting", Etc.
Usually there are not to many places in the logic you wish a derived classes to perform there own logic.

Inheritance in C++ internals

Can some one explain me how inheritance is implemented in C++ ?
Does the base class gets actually copied to that location or just refers to that location ?
What happens if a function in base class is overridden in derived class ? Does it replace it with the new function or copies it in other location in derived class memory ?
first of all you need to understand that C++ is quite different to e.g. Java, because there is no notion of a "Class" retained at runtime. All OO-features are compiled down to things which could also be achieved by plain C or assembler.
Having said this, what acutally happens is that the compiler generates kind-of a struct, whenever you use your class definition. And when you invoke a "method" on your object, actually the compiler just encodes a call to a function which resides somewhere in the generated executable.
Now, if your class inherits from another class, the compiler somehow includes the fields of the baseclass in the struct he uses for the derived class. E.g. it could place these fields at the front and place the fields corresponding to the derived class after that. Please note: you must not make any assumptions regarding the concrete memory layout the C++ compiler uses. If you do so, you're basically on your own and loose any portability.
How is the inheritance implemented? well, it depends!
if you use a normal function, then the compiler will use the concrete type he's figured out and just encode a jump to the right function.
if you use a virtual function, the compiler will generate a vtable and generate code to look up a function pointer from that vtable, depending on the run time type of the object
This distinction is very important in practice. Note, it is not true that inheritance is allways implemented through a vtable in C++ (this is a common gotcha). Only if you mark a certain member function as virtual (or have done so for the same member function in a baseclass), then you'll get a call which is directed at runtime to the right function. Because of this, a virtual function call is much slower than a non-virtual call (might be several hundered times)
Inheritance in C++ is often accomplished via the vtable. The linked Wikipedia article is a good starting point for your questions. If I went into more detail in this answer, it would essentially be a regurgitation of it.