Consider a class D
inherited from two classes B
and C
, each of which inherits not-virtually class A
. There is a method f
in A
, and the same named method in B
hiding the method from A
. I would like to call A::f()
from B
-base class of D
object as follows:
struct A { void f() {} };
struct B : A { void f() {} };
struct C : A {};
struct D : B, C {};
int main() { D{}.B::A::f(); }
Unfortunately, it works only in MSVC, while both GCC and Clang produce the error:
error: 'A' is an ambiguous base of 'D'
demo: https://gcc.godbolt.org/z/jY3v876hK
It looks like GCC/Clang accept but completely ignore B::
prefix in B::A::f()
. Are they right in doing so according to the standard?
Yes, it's legal to inherit the same class twice.
Multiple Inheritance in C++ Multiple inheritance occurs when a class inherits from more than one base class. So the class can inherit features from multiple base classes using multiple inheritance. This is an important feature of object oriented programming languages such as C++.
You can derive a class from any number of base classes. Deriving a class from more than one direct base class is called multiple inheritance. The order of derivation is relevant only to determine the order of default initialization by constructors and cleanup by destructors.
Explanation: When the inheritance is private, the private methods in base class are inaccessible in the derived class (in C++). 2.
Are they right in doing so according to the standard?
Yes. The nested name specifier in A::
, B::A
, or D::B::A
all serve the same purpose, to name the class A
.
[basic.lookup.classref]
4 If the id-expression in a class member access is a qualified-id of the form
class-name-or-namespace-name::...
the
class-name-or-namespace-name
following the.
or->
operator is first looked up in the class of the object expression ([class.member.lookup]) and the name, if found, is used. Otherwise it is looked up in the context of the entire postfix-expression.
The nested name specifier does not name "a path" to the member, it names a base of D
. And to name A
results in ambiguity.
Other answers show why the compiler is correct.
In order to achieve what you want, you can do:
int main() { static_cast<B&&>(D{}).A::f(); }
It's a bit ugly, though.
https://gcc.godbolt.org/z/Mzs8rsdf5
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With