-1
#include <iostream>

using namespace std;

class A
{
    public:
    A(){cout<<"Constructing A \n";}
    ~A(){cout<<"Destructinf A \n";}
    int x;
};
class B : virtual public A
{
    public:
    B(){cout<<"Constructing B \n";}
    ~B(){cout<<"Destructinf B \n";}
    int x=20;
};

class C : virtual public A
{
    public:
    C(){cout<<"Constructing C \n";}
    ~C(){cout<<"Destructinf C \n";}
    int x=50;



};

class D : public B,public C
{
    public:
        D(){cout<<"Constructing D \n";}
        ~D(){cout<<"Destructinf D \n";}
};

int main()
{
    D obj;
    obj.x; //x invoked
    cout<<obj.x<<"\n";  

    return 0;
}

Output error: request for member ‘x’ is ambiguous

Although I have used virtual class, still I am getting the above error.Do I have to remove One of the x declared in class B and Class C or is there any way to solve this error

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
iamut04
  • 9
  • 1
  • Why do `B` and `C` need a specific `x` member ? Why not use the one they get from `A` base class and assign it with the proper value ? – wohlstad Sep 14 '22 at 13:15
  • Yes use mixin/crtp not multiple inheritance to combine functionality. In my book diamond inheritance is a design problem and thus should be solved before you start coding. (eg. https://www.fluentcpp.com/2017/12/12/mixin-classes-yang-crtp/) – Pepijn Kramer Sep 14 '22 at 13:15
  • The declarations of `x` on both child classes don't do what you think they do. They don't define the default value for `x` in `A`. That's not how C++ works. – Sam Varshavchik Sep 14 '22 at 13:17
  • okay that means I have to remove one of the x declared in of the class? – iamut04 Sep 14 '22 at 13:26
  • It is not clear which value do you actually expect `obj.x` to have ? `obj` is of type `D` which derives from both `B` and `C` and each of them seem to require a differnt value for `x`. – wohlstad Sep 14 '22 at 13:29

1 Answers1

1

The lookup set for the name x in the derived class D includes two names in its direct base classes { B::x, C::x }. So using the unqualified name x in these statements

obj.x; //x invoked
cout<<obj.x<<"\n";

is ambiguous.

You could use qualified names like for example

D obj;
cout<<obj.B::x<<"\n";
cout<<obj.C::x<<"\n";

If you will remove the data member x in one of the base classes of the class D then there will be no ambiguity and you may write (for example if to remove the data member x in the class B)

D obj;
cout<<obj.x<<"\n";
cout<<obj.C::x<<"\n";

If you want tp have one data member with the name x then remove it from the both classes B and C as for example

class B : virtual public A
{
    public:
    B() { x = 20; cout<<"Constructing B \n";}
    ~B(){cout<<"Destructinf B \n";}
};

class C : virtual public A
{
    public:
    C(){ x = 50; cout<<"Constructing C \n";}
    ~C(){cout<<"Destructinf C \n";}
}

Pay attention to that the destructor should be declared as virtual.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Ok, now I got my answer .thanks everybody for your help. – iamut04 Sep 14 '22 at 13:51
  • Welcome to StackOverflow. If an answer solves your problem you could click '✔' to mark it as an accepted answer. With enough rep you can _also_ upvote any helpful answer (see here: https://stackoverflow.com/help/someone-answers). – wohlstad Sep 14 '22 at 16:02