4

As written in "The C++ Programming Language 3.Edition - Bjarne Stroustrup". We can use scope solution to prevent ambiguity errors. The basic program which is in below, when i use 3 layer scope in class mix an error occurs. But when i use 2 layer no problem. What is wrong? or is it something like design issue? The error is;

deneme.cpp: In constructor ‘mix::mix(std::__cxx11::string, int)’:
deneme.cpp:45:22: error: ‘plane’ is an ambiguous base of ‘mix’
    pervaneli::plane::engine=b;

I don't want to make a diamond model. I am happy with two base (plane) classes. The thing that i just want to learn why it gives error when i use 3 layer scope. Thanks.

Note: Version is g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

#include<iostream>
#include<string>
using namespace std;

class plane{
    protected:
    int speed;
    string name;
    public:
        int engine;
        void its_name(){
            cout<<name<<endl;
        }
        plane(int a=10000){
            engine=a;
        }

};

class pervaneli:public plane{
    public:
        pervaneli(string a="-"){
            name=a;
        }
        void belirle(int x){
            speed=x;
        }
};

class jet:public plane{
    public:
        jet(string a="-"){
            name=a;
        }
        void belirle(int x){
            speed=x;
        }
};

class mix: public pervaneli,public jet{
    public:
        mix(string a,int b){
            jet::name=a;
            pervaneli::name=a;
            pervaneli::plane::engine=b; //ambigous base error
            //pervaneli::engine=b; /*works fine*/
        } 
        void belirle(int x){
            jet::speed=x;
        }
};


int main()
    {
    mix a400m("Alp",9999);
    a400m.belirle(500);
    a400m.pervaneli::its_name();
    return 0;
    }
al0s
  • 151
  • 5
  • Maybe dupe (it answers your problem): http://stackoverflow.com/questions/21558/in-c-what-is-a-virtual-base-class – Rakete1111 May 03 '17 at 17:23
  • It is not about virtual. I don't want to make a diamond model. – al0s May 03 '17 at 17:24
  • 6
    Yes, it is. Your code suffers from the Diamond problem, which can be solved using virtual inheritance. – Rakete1111 May 03 '17 at 17:25
  • @Rakete1111 I Don't want to make Diamond. I exactly want two plane base classes. The problem is why does it give error when i use 3 layer scope. – al0s May 03 '17 at 17:27
  • Whether it is your intention or not, the compiler will recognize it as a diamond pattern with an ambiguous call as result. The answer of Rakete1111 with virtual is the way to go. – D.J. Klomp May 03 '17 at 17:44
  • 3
    I think `pervaneli::plane::engine` is `typename` `pervaneli::plane` `::engine`. So `plane::engine` which is ambiguous. – Jarod42 May 03 '17 at 17:46
  • 4
    @GillBates: OP has and wants Y inheritance, not a diamond (with virtual inheritance). – Jarod42 May 03 '17 at 17:52
  • The question is more interesting than critiquing OP for the diamond, i.e. why doesn't pervaneli::plane identify the correct base instance when pervanelli does. – Captain Giraffe May 03 '17 at 17:56
  • I don't want to make this functionless (i mean stupid) code to work :) when i use 2 layers scope it works properly. I just want to learn why do i get error when use 3 layers scope. Please, don't suggest me to use virtual or any other. – al0s May 03 '17 at 18:01
  • 1
    Changing non-virtual to virtual inheritance is a **design** change; a design change is **never**, in itself, an appropriate solution to a **coding** problem. A coding problem can point to a possible design flaw, but, as the OP keep saying, in this case the design is correct. – Pete Becker May 03 '17 at 19:41
  • @Pete Yes, you are right. I noticed it too after giving it some thought :) thanks – Rakete1111 May 03 '17 at 19:49

2 Answers2

6

From qualified_lookup

pervaneli::plane is the injected-class-name plane (the type).

so pervaneli::plane::engine is in fact plane::engine, which is ambiguous as you have two base class plane.

You cannot give full path to the member you want.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • 2
    Yes, it's the type NOT the subobject, and note the difference between `this->pervaneli::plane::engine` and `static_cast(this)->plane::engine` – Ben Voigt May 03 '17 at 18:09
1

Public inheritance means is a relationship.
Reference: Effective C++: Item 32: Make sure public inheritance models “is-a.”

So pervaneli is a plane because of public inheritance. The class pervaneli already has the member variable engine in it because of is a relationship with plane.

By adding the scope of plane you are making it ambiguous for the compiler hence the error.

ani627
  • 5,578
  • 8
  • 39
  • 45