#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)
重载。为什么?
答案 0 :(得分:13)
此运算符operator=(const string& ss)
需要将参数的用户定义类型转换为const char*
到std::string
),而bool
版本则没有,因此提供了更好的匹配:您可以获得从内置类型const char[5]
到const char*
到bool
的转化。
答案 1 :(得分:1)
正如另一个答案所指出的那样,首选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
的变量列表,它不能存在,其唯一目的是确保两个模板的编写方式不同,使编译器不要抱怨。)
答案 2 :(得分:0)
在没有深入研究C ++标准的情况下,表面上你的问题是,你用字符串&amp;来定义你的赋值重载。和一个布尔,但在你的测试中,你正在分配一个char *数组。
因此,如果你定义一个字符串并赋值,它将按预期工作。
检查它在这里工作:http://codepad.org/owb6noXR
答案 3 :(得分:0)
正如其他人所说,一个简单的解决方法是在执行运算符时简单地将字符串转换为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;
}