[英]Diamond of death and Scope resolution operator (c++)
我有此代码(钻石问题):
#include <iostream>
using namespace std;
struct Top
{
void print() { cout << "Top::print()" << endl; }
};
struct Right : Top
{
void print() { cout << "Right::print()" << endl; }
};
struct Left : Top
{
void print() { cout << "Left::print()" << endl; }
};
struct Bottom: Right, Left{};
int main()
{
Bottom b;
b.Right::Top::print();
}
我想在Top
类中调用print()
。
当我尝试对其进行编译时,出现错误: 'Top' is an ambiguous base of 'Bottom'
此行上'Top' is an ambiguous base of 'Bottom'
: b.Right::Top::print();
为什么模棱两可? 我明确指定要从Right
Top
Right
而不是“ Top
Left
。
我不想知道如何去做,是的,它可以通过引用,虚拟继承等来完成。我只是想知道为什么b.Right::Top::print();
暧昧。
为什么模棱两可? 我明确指定要从
Right
Top
Right
而不是“Top
Left
。
那是您的意图,但实际上并非如此。 Right::Top::print()
明确命名您要调用的成员函数,即&Top::print
。 但是它没有指定我们在b
哪个子对象上调用该成员函数。 您的代码在概念上等效于:
auto print = &Bottom::Right::Top::print; // ok
(b.*print)(); // error
选择print
的部分是明确的。 从b
到Top
的隐式转换是模棱两可的。 您必须通过执行以下操作来明确消除前进的方向:
static_cast<Right&>(b).Top::print();
范围解析运算符是左关联的(尽管它不允许使用括号)。
因此,虽然您想在B
内部引用A::tell
,但id-expression却在B::A
内部tell
,这就是A
,这是模棱两可的。
解决方法是先强制转换为明确的基B
,然后再次强制转换为A
语言咨询:
[basic.lookup.qual] / 1说,
在将
::
作用域解析运算符应用于表示其类,名称空间或枚举的嵌套名称说明符之后,::
类或名称空间成员或枚举器的名称 。
嵌套名称说明符的相关语法为:
嵌套名称说明符:
类型名称
::
嵌套名称说明 标识符
::
因此,第一个嵌套名称说明符是B::
并且在其中查找A
然后B::A
是表示A
的嵌套名称说明符,并在其中查找tell
。
显然,MSVC接受该示例。 它可能具有非标准扩展,可以通过在此类说明符中回溯来解决歧义。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.