7

我有这堂课:

class MyClass {

    public:

        int operator[](const std::string&);
        const std::string& operator[](const int&) const;

    ...
};

但是,如果我用 const 文字 0 调用第二个运算符,它的效果很好:

MyClass myclass;
std::cout << myclass[0] << std::endl;

我收到了这个错误:

In function 'int main()':
ambiguous overload for 'operator[]' in 'myclass[0]'
note: candidates are:
note: const int MyClass::operator[](const string&)|
note: const string& MyClass::operator[](const int&) const

我想我明白是什么情况(0 可以是字符串或整数?),但我的问题是:有没有办法解决这个问题并保持运算符重载?

4

3 回答 3

7

调用MyClass::operator[](const std::string&)涉及转换:

myclassMyClass&MyClass&: 完美匹配

0from intto const char*to std::string: 用户自定义转换

调用MyClass::operator[](const int&) const涉及转换:

myclassfrom MyClass&to const MyClass&: 常量限定

0intint: 完美匹配

在这种情况下,当一个重载对参数 X “更好”,但另一个重载对参数 Y “更好”时,这两个重载都不能被认为是最好的重载,编译器必须抱怨(假设没有第三个重载胜过两者) .

是否可以将两个重载更改为 bothconst或 both non-const?如果没有,您可以添加第三个重载来处理这种情况:

const std::string& operator[](int n) {
    return static_cast<const MyClass&>(*this)[n];
}
于 2012-12-20T19:54:40.580 回答
4

0不能是 a string,但它可以是指针,这意味着它可以隐式转换为 a string。请注意,这不适用于其他常量积分,例如142- 只是0具体而言。

4.10 指针转换

1/空指针常量是整数类型的整数常量表达式 (5.19) 右值,其计算结果为零。空指针常量可以转换为指针类型;结果是该类型的空指针值,并且可以与指向对象的指针或指向函数类型的指针的所有其他值区分开来。相同类型的两个空指针值应比较相等。将空指针常量转换为指向 cv 限定类型的指针是一次转换,而不是指针转换后跟限定转换 (4.4) 的顺序。

因此,在 的情况下myclass[0]0可以是int或 ` 空指针常量。

标准还规定有一个带指针std::string的非explicit构造函数:char

size_type find_last_not_of (const charT* s, size_type pos = npos) const;

现在,由于您的operator&方法都采用const引用类型的参数,因此可以将它们传递给临时对象。这就是编译器感到困惑的原因——它不知道你想要哪一个——一个接受一个int,或者一个接受一个临时string构造的 via string(const char*)

至于如何解决这个问题,我会退后一步。在我看来,你的两个operator[]函数做了截然不同的事情。或者也许他们会做同样的事情,给定不同的输入。如果他们做不同的事情,那么我将提供具有不同(适当)名称的成员函数,并跳过尝试使用operator[]语法。也许其中一种方法会返回真正被索引的东西——在这种情况下,我会使用那个operator[]语法,但只使用那个。

如果他们确实做同样的事情,并且那个事情是按索引返回一个项目,那么我将为此只提供一种方法,并让它size_t按值取值。然后,您还可以提供某种转换函数(最好以自由的非成员函数的形式),例如将 a 转换string为 a size_t。这样做,您可以在索引时编写这样的代码string

myPos[str_to_index(str)];
于 2012-12-20T19:55:44.963 回答
3

字面意思0很特别。除了作为八进制常量外,它还可以转换为任何指针类型的空指针。这使得. 的-constructor0可行。char const *std::string

两个重载都不是更好的原因是因为运算符的 int 重载具有const实例 CV 限定符。这样,两个重载都需要转换并且同样糟糕。

明显的解决方法是明确要求 const 重载:

static_cast<MyClass const &>(myclass)[0]
于 2012-12-20T19:47:16.470 回答