4

I understand the requirement of using virtual keyword when deriving from base classes to avoid diamond inheritance related ambiguity problems.

But, my question is why this is not the default behaviour in C++ when deriving classes regardless whether diamond problem could be or could not be there?

Is there any 'harm' of using 'virtual' keyword in a situation where diamond inheritance does not present?

Doonyx
  • 580
  • 3
  • 12
  • 1
    The harm is in using `virtual` keyword where it creates a diamond inheritance but that is unwanted. Consider a bank account that is a "DollarPaymentEndpoint" and a "YenPaymentEndpoint" where each of these inherit from "PaymentEndpoint" which has an "AmountReceived" member. – David Schwartz Feb 28 '14 at 00:51
  • 2
    [Why is the virtual keyword needed?](http://stackoverflow.com/questions/13600934/why-is-the-virtual-keyword-needed) discusses why `virtual` is not automatic. – Raymond Chen Feb 28 '14 at 00:52
  • 3
    @DavidSchwartz My mistake. Having virtual inheritance by default creates unexpected sharing and breaks encapsulation. it also prevents classes from being POD. – Raymond Chen Feb 28 '14 at 00:53
  • 2
    @RaymondChen: although the answer turns out to be very similar, I think that other question is intended to be about virtual member functions, whereas this question is intended to be about virtual inheritance. – Steve Jessop Feb 28 '14 at 00:58
  • 3
    Virtual inheritance doesn't avoid diamonds, it *creates* diamonds. – Kerrek SB Feb 28 '14 at 01:00
  • @KerrekSB: Very true, though I think the question is meant to be parsed as "to avoid (diamond inheritance related) ambiguity problems". – Mike Seymour Feb 28 '14 at 01:01
  • Could the answer simply be that the grammar would require a different keyword to specify when virtual inheritance was NOT wanted? Maybe re-use `explicit`, but I don't think that keyword was around when C++ grammar was developed – franji1 Feb 28 '14 at 01:13
  • "_This question already has an answer here_" No it does not – curiousguy Jul 16 '18 at 14:55
  • @franji1 `explicit` was added for one arg constructors, and the implicit conversion default is an error. What makes you think that non virtual default is an error? – curiousguy Jul 16 '18 at 15:13

2 Answers2

7

Virtual inheritance has a run-time overhead: converting pointers requires an adjustment that's only known at run time while, with non-virtual inheritance, it can be known at compile time. It can also make a class more complicated to derive from, since virtual base classes are initialised by the final derived class, not (necessarily) the class that inherits directly from them.

You would therefore only want it when you specifically want a diamond structure; it would be a pain to have to remember to specify non-virtual inheritance to avoid a hidden overhead. C++ generally follows the principle that you shouldn't pay for features you don't need.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
4

There's an overhead, try it:

#include <iostream>

struct Foo {
    int a;
};

struct Bar : Foo {
    int b;
};

struct Baz : virtual Foo {
    int b;
};

int main() {
    std::cout << sizeof(Foo) << " ";
    std::cout << sizeof(Bar) << " ";
    std::cout << sizeof(Baz) << "\n";
}

On my implementation I get 4 8 16. Virtual inheritance requires a vptr or equivalent mechanism, because the class Baz does not know at what offset the Foo base class sub-object will appear relative to the Baz base class sub-object. It depends whether the most-derived type also inherits Foo by another route.

Since the vptr is there, one also expects that in certain circumstances it will be used, which is more overhead :-) That is, one or more additional indirections are required in order to access Foo::a via a Baz* or Baz&. The compiler might choose to avoid that if it somehow knows the most-derived type of the referand.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699