Additionally if I understand this correctly virtual inheritance adds yet another v-table so the different bases can be distinguished, thus adding additional overhead to every drawable.
As for your example, you make the basic inheritance mistake so you can be a bit lazy with the interface implementaiton. Your FpsMeter is a Widget (I assume sf::Widget was a typo), but your FpsMeter has an sf::Text, as such the correct way is to inherit from Widget and add an sf::Text as composition. In fact, if you have more than one widget that are sort of like a text object, you could create an intermediate text widget which implements the specific interface and holds the sf::Text object.I already thought about it and for me it looks like FpsMeter is sf::Text, nothing more than sf::Text that changes it's state depending on delta time.
And at the end of the day, if you implement your own GUI system, you most likely do not want the widgets to be drawables directly, because you might want to perform some batching, depth resolving or similar things first, before actually rendering it to an SFML render target.I don't, it's just some simple code to add a few buttons to my game, if I wanted a GUI system I'd use tgui or sfgui. ;D
Diamond inheritance is not recommended and usually shows an abstraction/design issue. There's a reason why composition over inheritance is being repeated again and again.
I tested it before proposing change, there is no additional vtable nor any detectable overhead [...] and as virtual inheritance doesn't affect efficiencyThat's not exactly true, see here (http://stackoverflow.com/q/5553850/5427663) or here (http://www.codesynthesis.com/~boris/blog/2008/04/17/virtual-inheritance-overhead-gcc/). Making inheritance virtual for this very specific case imposes a potential penalty for 99% of sf::Drawable use cases where this is not necessary. I agree with eXpl0it3r regarding that careful design can usually avoid DoD relationships.
I already thought about it and for me it looks like FpsMeter is sf::Text, nothing more than sf::Text that changes it's state depending on delta time.sf::Text is a class to visualize text graphically and nothing more. Your FpsMeter however adds logic to it. Its purpose is to display the FPS; how this is done (by sf::Text) is an implementation detail. Many of the sf::Text methods may not be meaningful for your case, see LSP (https://en.wikipedia.org/wiki/Liskov_substitution_principle).
We can argue whether my use case is good example or not, there are situations in which multiple inheritance is recommendedYes, but multiple inheritance and Diamond-of-Death-relation are not equivalent.
That's not exactly true, see here (http://stackoverflow.com/q/5553850/5427663) or here (http://www.codesynthesis.com/~boris/blog/2008/04/17/virtual-inheritance-overhead-gcc/).First source is 5 years old, second – 8. :P
I agree with eXpl0it3r regarding that careful design can usually avoid DoD relationships.Yep, I agree. It's actually first situation since years when I realised I have fallen into diamond problem and I want to keep it that way.
Also, "detectable overhead" is very vague. Of course you won't see your game run at half the framerate because of virtual inheritance. But as SFML is a library that has thousands of different application scenarios, such analysis has to be taken very carefully, on multiple compilers, otherwise it's worthless. Your benchmark may not be representative because it uses a single translation unit, where the compiler can perform a lot of optimizations (static binding) because it sees all the involved classes. This may be different if this is offloaded to the linker, or even at runtime through dynamic libraries.You have a point. I tested it now with multiple translation units and dynamic linking – there's still no difference in execution time. Oh, well there is. ~0.1 second per 2000000000 calls with multiple translations units and ~0.1 second per 142857143 calls with dynamic linking, both are less than 1ns per call (same code but adjusted to multiple translation units and dynamic linking). Also keep in mind that my tests involve things that won't happen while using sf::Drawable (like member varialbe)
sf::Text is a class to visualize text graphically and nothing more. Your FpsMeter however adds logic to it. Its purpose is to display the FPS; how this is done (by sf::Text) is an implementation detail. Many of the sf::Text methods may not be meaningful for your case, see LSP (https://en.wikipedia.org/wiki/Liskov_substitution_principle).All methods existing in sf::Text are useful in FpsMeter, even sf::Text::setString. Oh, and I didn't break LSP, FpsMeter can be used everywhere where sf::Text is being used.
Yes, but multiple inheritance and Diamond-of-Death-relation are not equivalent.Multiple inheritance is most popular cause of DoD and as I stated a 'few' lines above, It's not DoD if virtual keyword is used (properly ofc).
All methods existing in sf::Text are useful in FpsMeter, even sf::Text::setStringSo what does your FpsMeter class do, then?
So what does your FpsMeter class do, then?