C++ 解决运算符[]的不明确重载
我有这门课:C++ 解决运算符[]的不明确重载,c++,operators,operator-overloading,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]
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;
我想我了解情况(0可以是字符串或int?),但我的问题是:有没有办法解决这个问题并保持运算符重载?文本
0
是特殊的。除了作为一个八进制常量外,它还可以转换为任何指针类型的空指针。这使得0
对于std::string
的char const*
-构造函数是可行的
这两种重载都不好的原因是运算符的int重载具有const
实例CV限定符。这样一来,两个重载都需要转换,并且同样糟糕
显而易见的解决方法是明确要求常量重载:
static_cast<MyClass const &>(myclass)[0]
static_cast(myclass)[0]
调用MyClass::operator[](const std::string&)
涉及转换:
myclass
从myclass&
到myclass&
:完美匹配
0
从int
到const char*
到std::string
:用户定义的转换
调用
MyClass::operator[](const int&)const
涉及转换:
myclass
从myclass&
到const myclass&
:const限定
0
从int
到int
:完美匹配
在这种情况下,当一个重载对参数X“更好”,而另一个重载对参数Y“更好”时,两个重载都不能被视为最佳重载,编译器必须抱怨(假设没有第三个重载比这两个重载都好)
是否可以将两个重载同时更改为常量
或同时更改为非常量
?如果没有,您可以添加第三个重载来处理这种情况:
const std::string& operator[](int n) {
return static_cast<const MyClass&>(*this)[n];
}
const std::字符串和运算符[](int n){
返回静态_cast(*this)[n];
}
0
不能是字符串
,但它可以是指针,这意味着它可以隐式转换为字符串
。请注意,对于其他常数积分,如1
或42
,这是不正确的,特别是0
4.10指针转换
1/空指针常量是整型常量表达式(5.19)
计算结果为零的整数类型的右值。空指针常量
可以转换为指针类型;结果是空指针
该类型的值,并可与
指向对象的指针或指向函数类型的指针。两个空指针值
同一类型的应进行同等比较。空指针的转换
指向cv限定类型指针的常量是单个转换,并且
不是指针转换后的限定顺序
转换(4.4)
因此,在myclass[0]
的情况下,0
可以是int
或`空指针常量
该标准还规定,std::string
具有非显式
构造函数,该构造函数采用char
指针:
size_type find_last_not_of (const charT* s, size_type pos = npos) const;
现在,由于您的操作符和方法都采用const
引用类型的参数,因此可以将它们传递给临时变量。这就是为什么编译器会感到困惑的原因——它不知道您想要哪一个——接受int
的编译器,还是接受通过string(const char*)
构造的临时字符串的编译器
至于如何解决这个问题,我会退后一步。在我看来,您的两个操作符[]
函数做的事情截然不同。或者他们做同样的事情,给予不同的输入。如果它们做不同的事情,那么我将提供具有不同(适当)名称的成员函数,并跳过尝试使用运算符[]
语法。也许其中一个方法返回的是真正被索引的东西——在这种情况下,我会使用操作符[]
语法来表示这个方法,但仅限于那个方法
如果他们真的做了同样的事情,那就是按索引返回一个项目,那么我只提供一种方法,让它按值取size\u t
。然后,您还可以提供某种转换函数(最好是以自由、非成员函数的形式),将字符串转换为大小。这样,在通过字符串编制索引时,您可以这样编写代码:
myPos[str_to_index(str)];
为什么要费心于const int&
?只需取一个int
。字符串
版本匹配,因为常量文本零可以隐式转换为nullconst char*
指针,然后从那里转换为std::string
。仍在考虑如何避免这种情况。我很惊讶这些被认为是相等的秩转换。返回const int
很奇怪(而且毫无意义)。@sftrabbit:这是实例上const
限定的原因。没有它,一个会是一个更好的超载。谢谢!现在,我只是删除了const
CV限定符作为解决方法。对于那些感到困惑的人,这里有两个参数:this指针和括号内的参数。运算符的第一个版本不要求第一个参数进行转换,第二个参数先进行int到指针的转换,然后再进行用户定义的转换。运算符的第二个版本要求对第一个参数进行常量转换,而对第二个参数不进行转换。所以第一个版本在第一个参数上更好,第二个版本在第二个参数上更好。由于两者对于所有参数都不相同或更好,因此它的模糊const限定转换是标准转换,而字符串(0)是用户定义的转换,因此没有歧义。谢谢!正如我在给Ker的评论中提到的
myPos[str_to_index(str)];