13
#include <iostream>
struct B1
{
    virtual void method()=0;
    virtual ~B1(){}
};

struct B2
{
    virtual void method()=0;
    virtual ~B2(){}
};

struct D: B1, B2
{
    virtual void method()
    {
        std::cout << "D::method\n";
    };
};

int main(int argc,char *argv[])
{
    D d;
    B1 &b1=d;
    B2 &b2=d;
    b1.method();
    b2.method();
    return 0;
}

Note, B1 and B2 do not share common interface.

Is it this legal? If yes - in which standard? C++98/03/11 ?

Both, msvc and gcc have compiled it OK.

Previously I thought, that I have to use some common interface for such case (possible virtual inheritence).

Does such situation have some special name?

How it works in details, please? Maybe some ISO references?

John
  • 749
  • 8
  • 17
  • 1
    If you explain what leads you to think it's a special case someone may find a good explanation. – Johan Lundberg Jul 12 '12 at 20:19
  • Because in that case, I expect to have two different *independed* inherited virtual functions in D: B1::method and B2::method. – John Jul 12 '12 at 20:22

2 Answers2

7

Your code is well-formed: void D::method() overrides both void B1::method() and void B2::method().

The specification states (C++11 §10.3/2):

If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list, cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.

B1 declares a virtual member function void B1::method(). Class D is derived from B1 and it also declares a member function with the same name (method), the same parameter list (no parameters), the same cv-qualification (no qualification) and the same ref-qualifier (no qualification).

Therefore, void D::method() overrides void B1::method().

The same logic applies for void B2::method() (just substitute B2 for B1 in the above explanation), so void D::method() overrides both void B1::method() and void B2::method().

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • Thank you, that sounds as true. I have found simmilar items on C++03 and C++98. But, I am curious, are there some additions in standard to that situation? Maybe some special notes for multiple inheritance? – John Jul 12 '12 at 20:47
  • Aside from the "and ref-qualifier," I would expect the specification to be the same in C++98 and C++03. – James McNellis Jul 12 '12 at 20:48
  • Great, that's good to know. By the way, just *using* method() *without* overriding it is only allowed for D if D is accessed through base class references/pointers. Compare http://stackoverflow.com/questions/3310910/method-resolution-order-in-c/3310948#3310948 – Johan Lundberg Jul 12 '12 at 20:56
  • 1
    Your explanation makes sense, but it's still surprising. The same body of code is implementing two different methods simultaneously, since surely B1::method and B2::method are unrelated. – Mark Ransom Jul 12 '12 at 21:07
  • If I had a dollar for every surprising thing I've learned about C++... well, I'd have a lot of dollars. – James McNellis Jul 12 '12 at 21:18
  • I hope that would be not suprise for some compiler developer. – John Jul 12 '12 at 21:46
  • @MarkRansom Overriding was always implicit in the original C++. Let's say you derive from some `Base` class, add a bunch of methods. Then the `Base` class is upgraded by its author to provide a few more methods, some of which are virtual. One of these new methods has the same name, argument list, cv-qualification... as one of your derived class methods. You now override a base class method, not knowing it, and without even a diagnostic in most (all?) IDE. – curiousguy Jul 21 '12 at 01:33
1

afaik this is legal in every standart. i'm not sure if it has it's own special name, but it is similar to the diamond problem .

if you override "virtual void method()" in D, then you override both the method in B1 and B2.

Edit:

to anwser why you do not have "two different independed inherited virtual functions in D: B1::method and B2::method":

when overriding a method, you can can only specify the function name, return type and parameters, but you can not add signature details about which one you inherit from when overriding.

imagine that it would be possible, then it could look something like this:

struct D: B1, B2
{
    virtual void B1::method()
    {
        std::cout << "D::method\n";
    };
    virtual void B2::method()
    {
        std::cout << "D::method\n";
    };
};

but seeing this, you can already say that there is no possibility to have something like that, because when calling

objectD.method()

you can not specify which one you are calling. so even if there was a way to overload both, there is still the problem of distinguishing on the function call.

EDIT: "can not specify which one you are calling." refers to, you can not specify whether you want to call a class D overload of B2::method or the B2 method itself. objectD.B2::method will always invoke the B2 (not overloaded) method (which in this case won't compile as B2 has no implementation)

cppanda
  • 1,235
  • 1
  • 15
  • 29
  • Thank you, I understood this. I would like to know some more details, because it is a little bit surprising to me. – John Jul 12 '12 at 20:14
  • @James McNellis wouldn't that only be possible inside a class member? void B1method(){ B1::method } ? – cppanda Jul 12 '12 at 20:53
  • i see. still they invoke the base class functions regardless of overloading. – cppanda Jul 12 '12 at 21:40
  • "_imagine that it would be possible, then it could look something like this:_" then you get a function named `B1::method`, and whose qualified name is `D::B1::method`! But in C++ `D::B1` means `B1`! When the **unqualified** name of a function `B1::method`, you know there is a problem. "_so even if there was a way to overload both,_" it would *not* be overloading, as functions have different names: `B1::method` vs `B2::method`! You can try as much as you want, I just don't think you can make this idea work. (But trying is fun. ;) – curiousguy Jul 21 '12 at 01:21