0

I've already reviewed several similar questions at StackOverflow, but nothing helps. I can't understand why the keyword using in my class NetflixCanada does not resolve the ambiguity.

What I want to achieve: to access 2nd time a private method from NetflixUkraine class.

Anyway, this is the code:

#include <iostream>
using namespace std;

void greetings(){
    cout << "\e[1mHi! This is a Netflix country review:\e[0m\n";
}

class NetflixUkraine {
    private:
    string mostPplrBrowserFrNTflx;

    public:
    string countryName; 
    int amountMedia = 5000;
    void uniqueMedia(){
        cout << "We have john Wick II\n";
    }
    
        void setBrowser(string amostPplrBrowserFrNTflx){
        if (amostPplrBrowserFrNTflx == "Chrome" || amostPplrBrowserFrNTflx == "Firefox" || 
        amostPplrBrowserFrNTflx == "Safari" || amostPplrBrowserFrNTflx == "Opera"){

            mostPplrBrowserFrNTflx = amostPplrBrowserFrNTflx;
        }

        else {
            mostPplrBrowserFrNTflx = "\nCannot define a web browser!\n";
        }
        }


        string getBrowser(){
            return mostPplrBrowserFrNTflx;
        }
};

class NetflixPoland: public NetflixUkraine { 
   public:
    void uniqueMedia(){
        cout << "We have john Wick II and III\n"; //method overriding
    }
   

   string doPolesLoveNtflx(bool answer){ //extending inheritance    
       if (answer == 1){
            return "Poles love Netflix";
       }
       else{
            return "Poles don't love Netflix";
       }
   }
};

class NetflixCanada: public NetflixUkraine, public NetflixPoland{
    public:
    using NetflixUkraine::setBrowser;
};

int main()
{
    greetings();

    //printing output
    NetflixUkraine library1;
    library1.countryName = "Ukraine";
    cout<< library1.countryName<<endl << library1.amountMedia << endl;
    library1.uniqueMedia(); //printing out the unique media


    NetflixPoland library3;
    library3.countryName = "\nPoland";
    cout << library3.countryName<< endl;
    library3.uniqueMedia();
    cout << library3.doPolesLoveNtflx(true) << endl;
    
    //adding a fav browser for watching Netflix
    library3.setBrowser("Chrome");
    cout << "most popular browser for watching Netflix: " << library3.getBrowser() << endl;

    NetflixCanada library4;
    library4.NetflixUkraine::setBrowser ("Chrome");

    return 0;
}

Output:


[12inheritance.cpp 2020-10-10 11:41:07.556]
,,12inheritance.cpp:65:7: warning: direct base ‘NetflixUkraine’ inaccessible in ‘NetflixCanada’ due to ambiguity
   65 | class NetflixCanada: public NetflixUkraine, public NetflixPoland{
      |       ^~~~~~~~~~~~~
12inheritance.cpp: In function ‘int main()’:
12inheritance.cpp:96:30: error: ‘NetflixUkraine’ is an ambiguous base of ‘NetflixCanada’
   96 |     library4.NetflixUkraine::setBrowser ("Chrome");
      |                              ^~~~~~~~~~
max
  • 166
  • 13
  • Your inheritance structure is known as "The Deadly Diamond of Death". As the name suggests, it is best avoided. You want to read about virtual inheritance. – n. m. could be an AI Oct 10 '20 at 11:55
  • 1
    There are two base instance of `NetflixUkraine` in the inheritance hierarchy of `NetflixCanada`. Draw a graph on some paper and it better be obvious. Ultimately, the compiler has no clue which one you're referring to when you specify `library4.NetflixUkraine::` And @n.'pronouns'm., there is no diamond here, that's part of the problem. Rather, its a Y-fork. A diamond gets its shape by utilizing virtual base classes, of which there are none here, and before using one, the OP should take your advice and question the design in the first place. – WhozCraig Oct 10 '20 at 11:55
  • Also, the `using namespace std;` has nothing to do with your problem; it just saves you typing `std::` when calling calling functions that are in the `std` namespace. If you are learning c++, I'd recommend that you avoid `using namespace foo` until you have a firm grasp of how scoping works. – user888379 Oct 10 '20 at 12:17
  • @user888379 I was not referring to using namespace std; but using NetflixUkraine::setBrowser; – max Oct 10 '20 at 12:36
  • @max I'm afraid that `using namespace std;` is a pet peeve of mine, and I didn't read your question as carefully as I should have. Sorry about that. – user888379 Oct 10 '20 at 13:25

1 Answers1

1

Your compiler can not distinguish between:

NetflixCanada::NetflixUkraine::setBrowser

and

NetflixCanada::NetflixPoland::NetflixUkraine::setBrowser

As mention in the comments, read about "The deadly diamond of death"

Pablo Yaggi
  • 1,061
  • 5
  • 14
  • Thank you for your solution Pablo Yaggi. However, now I'm confused about which solution I should check: either your "The deadly diamond of death" or from @WhozCraig "Y-fork". – max Oct 10 '20 at 18:13
  • The concept is almost the same, the information in the document is very descriptive, that is why I pointed to you. You should avoid that kind of inheritance in my opinion. – Pablo Yaggi Oct 10 '20 at 18:29
  • I've read the article but it is not clear why I cannot do the following: ``` library4.amountMedia = 1200; ``` According to the article you've mentioned, the "Diamond Problem" occurs when we deal with the method or value overriding, but the code above does have neither of those. Thus, why it happens, and how to resolve? Thank you. – max Oct 10 '20 at 21:18
  • The problem is the same, is not restricted to values. The problem is when the compiler can not decide which path to follow. Do the following exercise, explain which should the compiler follow, and why. – Pablo Yaggi Oct 17 '20 at 01:37