Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call a hidden method from two times inherited base class in C++?

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?

like image 220
Fedor Avatar asked Aug 31 '21 18:08

Fedor


People also ask

Can a class directly inherit from the same base class twice?

Yes, it's legal to inherit the same class twice.

Can we achieve multiple inheritance in C?

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++.

Can you inherit from multiple base classes?

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.

When the inheritance is private the private methods in base class are in C ++)?

Explanation: When the inheritance is private, the private methods in base class are inaccessible in the derived class (in C++). 2.


2 Answers

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.

like image 56
StoryTeller - Unslander Monica Avatar answered Oct 21 '22 13:10

StoryTeller - Unslander Monica


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

like image 34
Jeffrey Avatar answered Oct 21 '22 15:10

Jeffrey