我对这种情况感到困惑,谷歌搜索没有给我答案。基本上我有以下不编译的简单代码:
#include <iostream>
class A
{
public:
int a(int c = 0) { return 1; }
static int a() { return 2; }
};
int main()
{
std::cout << A::a() << std::endl;
return 0;
}
在编译时,GCC 4.2表示A::a()
中对main()
的调用对a()
个有效候选版本的两个版本都不明确。 Apple的LLVM编译器3.0编译时没有错误。
为什么gcc对我要调用哪个函数感到困惑?我认为显而易见的是,通过a()
对A::
进行限定,我要求static
版本的功能。当然,如果删除static
函数a()
,此代码仍然无法编译,因为A::a()
不是调用非static
a()
的有效语法。
感谢您的任何评论!
答案 0 :(得分:6)
原因是因为C ++指定这是不明确的。重载决策指定对于A::a
,由于this
不在范围内,该调用中的参数列表由设计的A对象参数而不是{{1}增强}。重载决策不排除非静态成员函数,而是
如果参数列表被设计对象增强,并且重载决策选择了T的非静态成员函数之一,则调用格式不正确。
这最近在委员会的core issue 1005背景下进行了广泛的讨论。请参阅考虑更改此规则的core issue 364但未执行此操作。
答案 1 :(得分:3)
原因是名称解析在编译器执行任何其他操作之前发生,例如找出要使用的重载函数。
使用A::
对函数进行限定只是告诉编译器“查看A
内部以找到名称a
”。它实际上并没有帮助你解决你所指的功能。
修改强>
因此,当您键入A::a()
时,首先编译器会认为“在A
中查找成员函数或可以使用operator()
的成员”。
然后编译器认为,“好的,这里有两种可能性,哪一个被引用?a()
或a(int c = 0)
,默认为c=0
。不确定。
如果您删除了static关键字并调用了obj.a()
这样的函数,那么仍会存在歧义。
WRT LLVM的解析器
我会说它为你做了一些额外的工作,这是标准不要求的,假设A::a()
是静态的。