Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do Derived1::Base and Derived2::Base refer to the same type?

MSVC, Clang and GCC disagree on this code:

struct Base { int x; };
struct Der1 : public  Base {};
struct Der2 : public  Base {};

struct AllDer : public Der1, public Der2 {
    void foo() {
        Der1::Base::x = 5;
    }
};

Godbolt

GCC:

<source>: In member function 'void AllDer::foo()':    
<source>:10:21: error: 'Base' is an ambiguous base of 'AllDer'    
   10 |         Der1::Base::x = 5;    
      |                     ^    
Compiler returned: 1

Clang gives a similar error, and MSVC gives no error.

Who is right here?

I suppose this is covered in [class.member.lookup], but I have difficulties understanding what it is trying to tell me for this case. Please quote the relevant parts and if possible explain in plain English.

PS: Inspired by this question Why is Reference to Base Class ambiguous with :: -operator trough derived class?

PPS: Actually my doubt is whether Der1::Base refers to the type, that would be Base (and then Der2::Base is exactly the same type), or to the subobject. I am convinced that it is the first, but if it is the latter then MSVC would be right.

like image 889
463035818_is_not_a_number Avatar asked Apr 28 '20 09:04

463035818_is_not_a_number


People also ask

Can base and derived class have same function?

Suppose, the same function is defined in both the derived class and the based class. Now if we call this function using the object of the derived class, the function of the derived class is executed. This is known as function overriding in C++. The function in derived class overrides the function in base class.

Can a class be both a base class and a derived class?

A derived class can have only one direct base class.

Where is the derived class is derived from derived base both derived and base class?

Where is the derived class is derived from? Explanation: Because derived inherits functions and variables from base.

What happen if the base and derived class contains definition of a function with same prototype?

Answer: if the base and derived class contains definition of a function with same prototype then a Compiler reports an error on compilation.

Can a base class inherit a derived class reference?

No, that's not possible since assigning it to a derived class reference would be like saying "Base class is a fully capable substitute for derived class, it can do everything the derived class can do", which is not true since derived classes in general offer more functionality than their base class (at least, that's the idea behind inheritance).

How to get the derived instance of a base?

Usage for getting new derived Instance is var base = new Base (); base.Data = 1; var derived = base.As<Derived> (); Console.Write (derived.Data); // Would output 1

Can a derived class be cast to a base class?

19 Answers. It only knows about the members of the base class, and doesn't know anything about those of the derived class. The reason that you can cast an instance of the derived class to an instance of the base class is because the derived class actually already is an instance of the base class, since it has those members already.

What is the difference between base part and derived part?

When we create a Derived object, it contains a Base part (which is constructed first), and a Derived part (which is constructed second). Remember that inheritance implies an is-a relationship between two classes. Since a Derived is-a Base, it is appropriate that Derived contain a Base part.


Video Answer


2 Answers

To answer the question in the title, yes, Derived1::Base references the injected-class-name [class.pre] Base and so does Derived2::Base. Both refer to the class ::Base.

Now, if Base would have a static member x, then the lookup of Base::x would be unambiguous. There's only one.

The problem in this example is that x is a non-static member, and AllDer has two such members. You can disambiguate such access to x by specifying an unambiguous base class of AllDer which has only one x member. Derived1 is an unambiguous base class, and it has one x member, so Derived1::x unambiguously specifies which of the two x members in AllDer you mean. Base too has only one x member, but it is not an unambiguous base of AllDer. Every instance of AllDer has two sub-objects of type Base. Therefore Base::x is ambiguous in your example. And since Derived1::Base is just another name for Base, this remains ambiguous.

[class.member.lookup] specifies that x is looked up in the context of the nested-name-specifier, so that has to be resolved first. We are indeed looking for Base::x, not Derived1::x, because we started by resolving Derived1::Base as Base. This part succeeds, there's only one x in Base. Note 12 in [class.member.lookup] explicitly tells you that an using an unambiguous name lookup may still fail when there are multiple subobjects with that same name. D::i in that example is basically your Base::x.

like image 142
MSalters Avatar answered Nov 03 '22 20:11

MSalters


The reason you can refer to the class name as a member of the class is because cpp aliases it for convenient use, as if you wrote using Base = ::Base; inside Base.
The problem you’re facing is that Der1::Base is Base.
Thus, when you write Der1::Base::x, it’s the same as Base::x.

like image 45
Dani Avatar answered Nov 03 '22 21:11

Dani