Diamond of death and Scope resolution operator (c++)

后端 未结 3 501
遇见更好的自我
遇见更好的自我 2021-01-11 10:55

I have this code (diamond problem):

#include 
using namespace std;

struct Top
{
    void print() { cout << \"Top::print()\" << e         


        
相关标签:
3条回答
  • 2021-01-11 11:36

    Actually, giving code is working fine as I tried it on Visual Studio 2019. There are two way to solve Diamond Problem; - Using Scope resolution operator - Inherit base class as virtual

    Calling print function by b.Right::Top::print() should be executed with no errors. But there is still two objects of your base class (Top) referred from your Bottom class.

    You can find additional detail in here

    0 讨论(0)
  • 2021-01-11 11:37

    The scope resolution operator is left-associative (though it doesn't allow parentheses).

    So whereas you want to refer to A::tell inside B, the id-expression refers to tell inside B::A, which is simply A, which is ambiguous.

    The workaround is to first cast to the unambiguous base B, then cast again to A.

    Language-lawyering:

    [basic.lookup.qual]/1 says,

    The name of a class or namespace member or enumerator can be referred to after the :: scope resolution operator applied to a nested-name-specifier that denotes its class, namespace, or enumeration.

    The relevant grammar for nested-name-specifier is,

    nested-name-specifier:

        type-name ::

        nested-name-specifier identifier ::

    So, the first nested-name-specifier is B:: and A is looked up within it. Then B::A is a nested-name-specifier denoting A and tell is looked up within it.

    Apparently MSVC accepts the example. Probably it has a nonstandard extension, to resolve ambiguity by backtracking through such specifiers.

    0 讨论(0)
  • 2021-01-11 11:54

    Why is it ambiguous? I explicitly specified that I want Top from Right and not from Left.

    That was your intent, but that's not what actually happens. Right::Top::print() explicitly names the member function that you want to call, which is &Top::print. But it does not specify on which subobject of b we are calling that member function on. Your code is equivalent conceptually to:

    auto print = &Bottom::Right::Top::print;  // ok
    (b.*print)();                             // error
    

    The part that selects print is unambiguous. It's the implicit conversion from b to Top that's ambiguous. You'd have to explicitly disambiguate which direction you're going in, by doing something like:

    static_cast<Right&>(b).Top::print();
    
    0 讨论(0)
提交回复
热议问题