考虑此类:

class Base{
public:
    void func(double a) = delete;
    void func(int a) const {}
};

int main(){
    Base base;

    base.func(1);
    return 0;
}

使用clang++编译时,会产生以下错误:

clang++ --std=c++11 test.cpp
test.cpp:22:7: error: call to member function 'func' is ambiguous
    base.func(1);

使用g++会产生警告:

g++ -std=c++11 test.cpp
test.cpp: In function ‘int main()’:
test.cpp:22:13: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: base.func(1);

为什么此代码不明确?

最佳答案

非静态成员函数,类似于两个:

void func(double);    // #1
void func(int) const; // #2
还接受一个implicit object parameter,它在重载解析([over.match]/p1)中被视为任何其他参数:

将隐式对象参数合并到成员函数签名后,编译器会看到两个重载:
void func(Base&, double);    // #1
void func(const Base&, int); // #2
并尝试根据调用选择最佳可行的功能:
Base base;
base.func(1);
base(是Base类型的非常量左值)到Base&的转换具有完全匹配等级(直接引用绑定(bind)会产生Identity conversion)-请参见Table 13。从baseconst Base&的转换也具有完全匹配等级,但是[over.ics.rank]/p3.2.6声明#1具有更好的转换顺序:

现在,对于第二个参数,从积分prvalue 1double的转换是浮点积分转换([conv.fpint]),该转换被赋予了转换等级。另一方面,1int是完全转换等级的身份转换。对于此参数,#2被认为具有更好的转换顺序([over.ics.rank]/p3.2.2):

要成功解决重载,就需要最多存在一个转换顺序不同的参数([over.match.best]):

在这里,ICS0(#1)优于ICS0(#2),但是ICS1(#2)却比ICS1(#1)好,因此编译器无法在两个重载之间进行选择并检测到歧义。

关于c++ - 为什么对成员函数的调用不明确?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42573771/

10-11 15:56