奇怪的操作符重载行为
Strange operator overloading behavior?
#include <iostream>
using namespace std;
class Foo{
string _s;
public:
Foo(string ss){
_s = ss;
}
Foo& operator=(bool b){
cout << "bool" << endl;
return *this;
}
Foo& operator=(const string& ss){
cout << "another one" << endl;
return *this;
}
};
int main(){
Foo f("bar");
f = "this";
return 0;
}
我重载了=
运算符。我期望f = "this";
语句调用operator=(const string& ss)
重载。但事实并非如此。它调用operator=(bool b)
过载。为什么?
operator=(const string& ss)
操作符需要对实参(const char*
到std::string
)进行用户定义类型的转换,而bool
版本没有,因此提供了更好的匹配:您可以从内置类型const char[5]
到const char*
再到bool
进行转换。
正如另一个答案所指出的,从指针到char到bool
的转换是首选的,因为它不涉及用户定义的转换,而std::string
转换中有用户定义的转换。
c++ 11提供了手动类型控制的能力。
template<size_t n>
struct enumarated_enum {
private:
enum empty {};
};
template<bool b, size_t n=0>
using EnableIf = typename std::enable_if< b, typename enumerated_enum<n>::empty >::type;
template<typename String, EnableIf< std::is_convertible< String, std::string >::value >... >
Foo& operator=(String&& s) {
cout << "string overload" << "n";
}
// either this:
template<typename Bool, EnableIf< !std::is_convertible< Bool, std::string >::value && std::is_convertible< Bool, bool >::value, 1 >... >
Foo& operator=(Bool&& b) {
cout << "bool overload" << "n";
}
// or this:
Foo& operator=(bool b) {
cout << "bool overload" << "n";
}
,如果类型可以转换为std::string
,则完全匹配,如果不能转换为std::string
,则模板不匹配,并查看其他重载。
如果您希望能够支持许多类型,则必须使用长逻辑形式来描述您想要运行的重载,并确保其他重载不接受它(使用上面的not结构)。如果您只有两种类型,那么第二种类型可以是传统的过载。模板重载首先处理与传统重载不完全匹配的内容…
(第二个模板参数是一个不能存在的编号enum
的可变列表,其唯一目的是确保两个模板在足够的方面不同,以便编译器不会报错。)
如果不深入研究c++标准,表面上你的问题是,你用string&一个bool值,但是在你的测试中你赋值了一个char*数组
所以如果你定义一个字符串并赋值,它将按预期工作。
检查它在这里工作:http://codepad.org/owb6noXR
正如其他人所说,解决这个问题的一个简单的方法是在执行操作符时将字符串强制转换为std::string
,这样c++就确切地知道选择哪个重载:
#include <iostream>
using namespace std;
class Foo{
string _s;
public:
Foo(string ss){
_s = ss;
}
Foo& operator=(bool b){
cout << "bool" << endl;
return *this;
}
Foo& operator=(const string& ss){
cout << "another one" << endl;
return *this;
}
};
int main(){
Foo f((string)"bar");
f = (string)"this";
return 0;
}
- 重载操作符+:表达式必须是整型或无作用域枚举类型
- 重载操作符
- 如何重载操作符==外模板类使用友元函数
- 重载*操作符,使其在左右两边都工作
- 重载操作符<对于非随机迭代器
- 在c++中重载操作符的时间和原因
- 如何在c++中重载=操作符来通过引用进行复制
- 如何在c++中获取定义为友元的重载操作符的地址
- 使用重载操作符的文件操作表达式没有给出预期的结果
- 重载操作符()
- 重载操作符()并在类内使用
- 类中的重载操作符+
- 定时使用重载操作符
- c++带类的重载操作符
- 用列表容器重载[]操作符
- 重载操作符=
- 任何重载操作符()的静态检测
- 重载操作符以处理类对象
- 在使用另一个类的类中重载操作符==
- 派生类和基类中的重载操作符不同