44

我最近修复了一个错误。

在下面的代码中,重载函数之一是 const 而另一个不是。该问题将通过将两个函数设为 const 来解决。

我的问题是为什么编译器只在参数为 0 时才抱怨它。

#include <iostream>
#include <string>

class CppSyntaxA
{
public:
    void f(int i = 0) const { i++; }
    void f(const std::string&){}
};

int main()
{
    CppSyntaxA a;
    a.f(1);  // OK
    //a.f(0);  //error C2666: 'CppSyntaxA::f': 2 overloads have similar conversions
    return 0;
}
4

2 回答 2

56

0在 C++ 中是特殊的。空指针的值是 ,0因此 C++ 将允许转换为0指针类型。这意味着当你打电话时

a.f(0);

您可以使用值为 的 进行调用void f(int i = 0) constint0可以void f(const std::string&)使用char*初始化为 null 的方式进行调用。

通常int版本会更好,因为它是完全匹配的,但在这种情况下int版本是const,因此它需要“转换”a为 a const CppSyntaxA,其中std::string版本不需要这样的转换,但确实需要先转换为char*,然后再转换为std::string。这在两种情况下都被认为是足够的变化,从而被认为是相等的转换,因此是模棱两可的。使这两个函数const或非函数const将解决问题,并且int将选择重载,因为它更好。

于 2019-07-18T20:07:30.320 回答
11

我的问题是为什么编译器只在参数为 0 时才抱怨它。

因为 0 不仅是整数文字,而且还是空指针文字。1 不是空指针文字,因此没有歧义。

歧义来自隐式转换构造函数,std::string它接受指向字符的指针作为参数。

现在,从 int 到 int 的单位转换将优于从指针到字符串的转换,但是还有另一个涉及转换的参数:隐式对象参数。在一种情况下,转换是 from CppSyntaxA&toCppSyntaxA&而在另一种情况下是CppSyntaxA&to const CppSyntaxA&

因此,由于一个参数而首选一个重载,并且由于另一个参数而首选另一个重载,因此没有明确的首选重载。

该问题将通过将两个函数设为 const 来解决。

如果两个重载都被const限定,则隐式对象参数转换序列是相同的,因此其中一个重载是明确首选的。

于 2019-07-18T20:12:47.810 回答