3

So I was wondering why the following code snippet of the diamond problem is not able to be compiled. I am aware that this problem is usually solved by virtual inheritance, i didn't use this on purpose. The code is just to showcase my question on why the compiler calls this ambiguous: So i have two member variables declared in struct Base, because the two subclasses (in this case structs) do not inherit virtually, i would have a reference to the Base members in each derived struct. Now I have another struct AllDer which would run in the problem of knowing id_ and name_ two times. However when i explicitly target id_ and name_ from Base, i don't understand why this would be ambiguous since the direct target variable is specified through the ::-operator.

cout << Der1::Base::id_ << Der1::Base::name_ << '\n';

Can somebody tell me, why the compiler runs into a problem here? (Please forgive possibly wrong technical terms) Compiler error message says: "ambiguous conversion from derived class 'AllDer' to base class". Using MinGW 7.3.0 64-bit for C++ in QT Creator.

EDIT: Since this problem seems to get handled differently by compilers, please check the linked question.

#include <string>
#include <iostream>
using std::string; using std::cout;

struct Base
{
    int id_;
    string name_; //target members for readAllDer() in AllDer

    void read()
    {
        cout << id_ << ' ' << name_ << '\n';
    }
};


struct Der1 : public  Base
{
    //Der1 has own reference to id_, name_
    void readDer1()
    {
        cout << id_ << name_ << '\n';
    }
};

struct Der2 : public  Base
{
    //Der2 has own reference to id_, name_
    void readDer2()
    {
        cout << id_ << name_ << '\n';
    }
};

//
struct AllDer : public Der1, public Der2
{

    void readAllDer()
    {
        cout << Der1::Base::id_ << Der1::Base::name_ << '\n'; // Why is this ambiguous? 
    }
};

Sören
  • 45
  • 4

3 Answers3

1

Der1::Base and Der2::Base are the same class and AllDer derives from it twice. Your method compiles when you pick the members not from Base but from Der1:

struct AllDer : public Der1, public Der2
{

    void readAllDer()
    {
        cout << Der1::id_ << Der1::name_ << '\n'; 
    }
};
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • This is not a virtual inheritance. I believe you are wrong. – Michael Apr 28 '20 at 09:11
  • @Micheal I dont understand what you say. There is no virtual inheritance in OPs code and I dont refer to virtual inheritance. If there was virtual inheritance then `AllDer` would only contain a single `Base` subobject and there would be no ambiguity – 463035818_is_not_an_ai Apr 28 '20 at 09:12
  • `Der1::Base` and `Der2::Base` are not the same object. They are two distinct objects of the same type. You can verify it by setting `Der1::Base::name_` to "A" and `Der2::Base::name_` to "B". – Michael Apr 28 '20 at 09:17
  • @Michael `Der1::Base` and `Der2::Base` aren't objects but types – 463035818_is_not_an_ai Apr 28 '20 at 09:18
  • Of course, I meant that in the context of writing `Der1::Base::name_` and `Der2::Base::name_`, you refer to the field `name_` of two distinct objects. – Michael Apr 28 '20 at 09:19
  • @Michael no, they are both refering to `Base`, the same type. Anyhow, I am considering to delete the answer because the question needs to be clarified but I think I'll just leave it – 463035818_is_not_an_ai Apr 28 '20 at 09:20
  • I added constructors, ```cpp AllDer() : Der1("Michael", 1), Der2("Daniel", 2) {} ``` And now ```cpp cout << Der1::Base::id_ << Der1::Base::name_ << '\n'; // Why is this ambiguous? cout << Der2::Base::id_ << Der2::Base::name_ << '\n'; // Why is this ambiguous? ``` Prints whta I expect, "1Michael\n2Daniel\n" – Michael Apr 28 '20 at 09:22
  • I strongly believe this is a gcc bug, I'll check on clang – Michael Apr 28 '20 at 09:23
  • @Michael I believe you that it works on msvc, but I believe that gcc and clang are right here. Otherwise there would be no problem with the diamond – 463035818_is_not_an_ai Apr 28 '20 at 09:25
  • @Michael opened a new question: https://stackoverflow.com/questions/61477009/is-derived1base-and-derived2base-refering-to-the-same-type – 463035818_is_not_an_ai Apr 28 '20 at 09:35
  • I understand why you can achieve accessing the Base members trough the directly derived classes. However my question is, why the compiler says Der1::Base:: ... is ambiguous since the access on the Base members should be clear as far as i understand. – Sören Apr 28 '20 at 10:28
  • 1
    @SörenHepp because `Der1::Base` is not an object, its a type and it is the same type as `Der2::Base`. I opened a new question, because I have my doubts (link above) – 463035818_is_not_an_ai Apr 28 '20 at 10:31
0

Its a classic diamond problem, even if you are saying you are specifying the direct target variable through scope(::) Here 'Der1' already has copy of 'id_,name_' and you are still trying to access base's copy which is ambiguous for 'AllDer' as its coming by two ways Der1 and Der2.

instead of this:

Der1::Base::id_

try this:

Der1::id_ and Der1::name_

hope this helps

Sachin Nale
  • 139
  • 2
  • 4
-1

you need to inherit Der1 and Der2 virtually from base class like this

struct Der1 : virtual public  Base


struct Der2 : virtual public  Base

in this LINK said: Virtual inheritance is a C++ technique that ensures only one copy of a base class's member variables are inherited by grandchild

MH Alikhani
  • 110
  • 7
  • OP is well aware of the double inheritance of `Base`, that's why he's trying to disambiguate `_id` member. – Yksisarvinen Apr 28 '20 at 09:11
  • i don't understand why this answer is wrong but thanks for your comment @Yksisarvinen – MH Alikhani Apr 28 '20 at 09:12
  • @Yksisarvinen i will be thanks full if you explain why – MH Alikhani Apr 28 '20 at 09:13
  • 3
    I'm not the one who downvoted it, but OP specifically doesn't want virtual inheritance ("*I am aware that this problem is usually solved by virtual inheritance, i didn't use this on purpose.*"). The question is "why `Der1::Base::_id` is ambiguous?" – Yksisarvinen Apr 28 '20 at 09:26