Virtual Inheritance should be default

Pages: 123
(Note: I don't actually want C++ to change, I just want to discuss my idea of a better OOP C++)
I really like how C++ solved common inhertance problems. I just have one complaint: public, protected, and even private inheritance should, by default, be virtual.

But what about subclasses having to initialize non-direct base classes?
At the point where the compiler can say "hey, you need to do that!", it should be able to see if specific classes are only inherited once, and, if so, default to whatever initialization code provided by a class in the chain closest to that base. (ofc that means that code would have to be in the class def and not the class impl) This should even work if the class is inherited multiple times (A, B:A, C:A, D:C, E:D - as long as D inits A, E is fine). If no inititialization code can be found then of course you have to do it yourself.

Virtual private inheritance!? That would mean subclasses could initialize private base classes!
Nope. In this case scope and visibility take charge. Only the direct subclass can initializ that base and only that direct subclass' inner classes that extend it could override that.

But when would you have a diamond inhertance problem with private inhertance?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Base {};
class SubA;
class SubB: public virtual Base {};
class Extender: public SubA, public SubB {};
class SubA: private virtual Base
{
    friend void foo(const Extender &);
};

void bar(const Base &);
void foo(const Extender &e)
{
    bar(e); //because foo is a friend of SubA, the call is ambiguous
    //The workaround would be to make a foohelper(const Extender &e)
    //that could only choose the Base from SubB, but that's silly
}
(This actually happened to me)

But what about class A, class B: private A, class C: public A, public B? Won't that give C access to B's private base class?
This is why I changed the post title from "manditory" to "default". In this case B could specify that it wanted its own instance of A by saying class B: private static A.

What about having to use that dynamic_cast that annoys some people?
Just...no...don't ask that.

Runtime overhead! The implementation uses an extra pointer! This is elss efficient! AHHHHHHHHH!
Read the first line of this post.


Let's discuss! Show me why this is a bad idea (assume efficiency and such are not goals).
Last edited on
Multiple inheritance of classes is a bad idea. You fixed a non-existent problem :P
Give me a reason, not related to any language, why multiple inheritance of classes in an object oriented environment is "a bad idea".
Give me a reason, not related to any language, why multiple inheritance of classes in an object oriented environment is "a bad idea".


Some java programmers people seem to believe that the diamond problem with multiple inheritance cannot be avoided unless support is explicitly stripped from the language. What frequently does happen though is that composite-code ends up cluttered with code duplication...effectively cutting off an arm to cure a hang-nail. These people also believe that having multiple base classes "needlessly complicates" solutions. You can either agree with them and their teachings, or you're wrong. {/sarcasm}
Last edited on
The reason this is not in c++ is because c++ was designed with the programmer never paying for something they don't need. That is the core value of c++

The question is: Why would inheritance always being virtual benefit OOP in c++. I understand that non-virtual inheritance is rarely useful, but what benefit is there to forcing virtual inheritance?
I'm just another guy that tries to make it hard for people to shoot themselves in the foot.
I'm just another guy that tries to make it hard for people to shoot themselves in the foot.
Note: I don't actually want C++ to change

I see...

Show me why this is a bad idea (assume efficiency and such are not goals).

Here's one reason: I have no idea what virtual inheritance does and neither does 90% of this forum.
Wait a minute, I'm confused now. Would this actually be a reason for making it mandatory? Food for thought!
No - when you do object oriented programming in C++, virtual inheritance solves the diamond inheritance problem.

I don't want C++ to change because, obviously, efficiency and reverse compatibility.
Relevant link:
http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem

@ LB: I believe this falls under the same category as virtual destructors in a base class: things that the compiler can, and should, do automatically when needed.

Some java programmers people seem to believe that the diamond problem with multiple inheritance cannot be avoided unless support is explicitly stripped from the language.


This is the opinion shared by probably all language designers except C++:
- Java: no class MI.
- Python: no class MI, only mixins
- Ruby: no class MI, only mixins
- Google Go: also not here
- Scala: only traits MI, but no class MI
- C#: neither here
- JavaScript: no classes at all, ability to inherit only from one prototype, 1.2 support mixins

Looks like the concept of multiple inheritance of classes has been abandoned (similarly to checked exceptions). Why? Because it causes more problems than it solves (does it solve any problem at all, that is not solved with multiple inheritance of interfaces / traits / mixins?)


What frequently does happen though is that composite-code ends up cluttered with code duplication...effectively cutting off an arm to cure a hang-nail.


Any example? Any example for good use of MI? Someone already gave an example how not to use MI in the different thread...

Last edited on
Any example for good use of MI?

http://en.cppreference.com/w/cpp/io/basic_iostream
No, it is not. The same design can be done with multiple inheritance of interfaces. No need to inherit classes.
closed account (o1vk4iN6)
Of course it is possible, that's why the language is turing complete. It is more intuitive to use multiple inheritance though. Again as the other thread, go look at 3DS Max API where there are many classes that inherit from dozens of other classes. Single inheritance would be unintuitive in this situation. The burden of proof falls on you stating that MI is a bad idea, trying to shift that burden onto someone else to try to counter your argument can only mean a few things :P. The languages you stated aren't as complex as C++, which is consider "advanced" and requires more knowledge and expertise to use effectively. Why exclude a feature that also requires more knowledge to use effectively. It seems to only make sense to include a feature such as that into C++, rather than another simpler language where the quality of programmers wouldn't permit them to use MI effectively.
Last edited on
They didn't include class MI in those newer and more advanced languages (Scala or C# have much more sophisticated type systems than C++), because there were no good examples of problems it really solves. Even if there are, they are extremely rare.
That 3DS uses it, ok, Linux kernel uses goto in various places. But that doesn't mean it is good nor we should use it in new programs.
Last edited on
I got the idea that MI wasn't a great idea from reading "Thinking in C++", by Bruce Eckel.

You can inherit from one class, so it would seem to make sense to
inherit from more than one class at a time. Indeed you can, but
whether it makes sense as part of a design is a subject of continuing
debate. One thing is generally agreed upon: You shouldn’t try this
until you’ve been programming quite a while and understand the
language thoroughly. By that time, you’ll probably realize that no
matter how much you think you absolutely must use multiple
inheritance, you can almost always get away with single
inheritance.
Initially, multiple inheritance seems simple enough: You add more
classes in the base-class list during inheritance, separated by
commas. However, multiple inheritance introduces a number of
possibilities for ambiguity, which is why a chapter in Volume 2 is
devoted to the subject.


http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html

vol 2 chapter 6 summary

The reason MI exists in C++ and not in other OOP languages is that C++ is a hybrid language
and couldn’t enforce a single monolithic class hierarchy the way Smalltalk does. Instead, C++
allows many inheritance trees to be formed, so sometimes you may need to combine the
interfaces from two or more trees into a new class.
If no “diamonds” appear in your class hierarchy, MI is fairly simple (although identical
function signatures in base classes must be resolved). If a diamond appears, then you must
deal with the problems of duplicate subobjects by introducing virtual base classes. This not
only adds confusion, but the underlying representation becomes more complex and less
efficient.
Multiple inheritance has been called the “goto of the 90’s”.22 This seems appropriate because,
like a goto, MI is best avoided in normal programming, but can occasionally be very useful.
It’s a “minor” but more advanced feature of C++, designed to solve problems that arise in
special situations. If you find yourself using it often, you may want to take a look at your
reasoning. A good Occam’s Razor is to ask, “Must I upcast to all of the base classes?” If not,
your life will be easier if you embed instances of all the classes you don’t need to upcast to.

Last edited on
The reason I don't like Java-style interfaces is because they can't have data members or pre-implemented methods. C++ pure virtual classes CAN have data members and implemented methods/constructors/destructor.

Consider Minecraft.
Entity class
Mob class extends Entity
Wolf, Ocelot, SomeNewMob, Cow, Pig, Zombie, and Creeper are all mobs.
Wolf, Ocelot, Cow, and Pig can all breed.
Wolf, Ocelot, and SomeNewMob can all be tamed.

To prevent code duplication, a Breedable class (extends Mob) can be created that implements breeding mechanics, and a Tameable class (extends Mob) can be created that implements taming mechanics. However this means that Wolf and Ocelot have to extend both Breedable and Tameable, which are classes with data members and concrete methods. In C++ there is no problem, assuming of course you use virtual inheritance, but in Java this problem cannot be solved effectively. You could make Breedable and/or Tameable interfaces, but then you have code duplication from using the same implementation twice, or you would have to place the implementation awkwardly in static methods and call them from the implementing methods.

Do you have a better solution?
Last edited on
Yeah, but that still doesn't justify class inheritance. What you are describing is a classical example for traits.


in Java this problem cannot be solved effectively. You could make Breedable and/or Tameable interfaces, but then you have code duplication from using the same implementation twice, or you would have to place the implementation awkwardly in static methods and call them from the implementing methods.


The implementation for taming and breeding can be placed in nested objects. There would be no code duplication, just a few delegation methods that can be autogenerated. Of course the trait mixin approach as in Ruby or Scala is a little cleaner, but it is not a game changer.
Last edited on
closed account (o1vk4iN6)
rapidcoder wrote:
That 3DS uses it, ok, Linux kernel uses goto in various places. But that doesn't mean it is good nor we should use it in new programs.


You're point ? That doesn't make 3DS max a bad example. Can name tons of Java programs that use inheritance, does that mean we shouldn't use inheritance because you are promoting Java ?
Last edited on
rapidcoder wrote:
The implementation for taming and breeding can be placed in nested objects.


So to keep code bloat under control, we escalate the number of classes that manage the solution and create new delegate methods that could eventually find their way into user-code? That doesn't sound right. Traits are a step in the right direction though...I'm curious to see if anything like that worms its way into Java 8, but I don't think that's very likely...

It seems that this way of thinking is moving away from an "is a" relationship to an "is capable of doing" relationship. Maybe we should rename object oriented programming to behavior oriented programming to match. If that's the case, then we're comparing apples to jet engines here and there isn't much of a debate left.
Last edited on
No, it is not. The same design can be done with multiple inheritance of interfaces. No need to inherit classes.

Interfaces? Do you mean abstract classes?
Because otherwise, you asked for an example of "good use" of MI, and I gave it from the C++ library, and then you say that it wouldn't be done that way in another language that doesn't support MI of classes in the first place.

Why isn't the iostream example "good"? It shows the benefits of code reuse from two classes, fully functional on their own.
Pages: 123