解决运算符[]的模糊重载

时间:2012-12-20 19:36:54

标签: c++ operators operator-overloading

我有这堂课:

class MyClass {

    public:

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

    ...
};

但是,如果我调用第二个运算符w / const literal 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可以是字符串或int?),但我的问题是:有没有办法解决这个问题并保持运算符重载?

3 个答案:

答案 0 :(得分:6)

致电MyClass::operator[](const std::string&)涉及转换:

myclassMyClass&MyClass&:完美匹配

0intconst char*

std::string:用户定义的转化

致电MyClass::operator[](const int&) const涉及转换:

myclassMyClass&const MyClass&:const qualified

0intint:完美匹配

在这种情况下,当一个重载对于参数X“更好”但是对于参数Y不同的重载“更好”时,过载都不能被认为是最好的重载,并且编译器必须抱怨(假设没有第三个过载)打败了。)

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

const std::string& operator[](int n) {
    return static_cast<const MyClass&>(*this)[n];
}

答案 1 :(得分:4)

0不能是string,但它可以是指针,这意味着它可以隐式转换string。请注意,其他常量积分不是这样,例如142 - 只是0

4.10指针转换

  

1 /空指针常量是一个整数常量表达式(5.19)   整数类型的rvalue,其值为零。空指针常量   可以转换为指针类型;结果是空指针   该类型的值,可以与其他每个值区分开来   指向对象的指针或指向函数类型的指针。两个空指针值   同一类型应相等。空指针的转换   指向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构建临时string(const char*)的那个

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

如果他们确实做了同样的事情,并且那件事是通过索引返回一个项目,那么我只提供一个方法,并让它采用size_t按价值。然后,您还可以提供某种转换功能(最好以免费的非会员功能的形式),例如,从string转换为size_t。这样做,您可以在string

索引时编写这样的代码
myPos[str_to_index(str)];

答案 2 :(得分:3)

文字0很特别。除了是八进制常量之外,它还可以转换为任何指针类型的空指针。这使得0的{​​{1}}构造函数char const *可用std::string

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

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

static_cast<MyClass const &>(myclass)[0]