奇怪的操作符重载行为

Strange operator overloading behavior?

本文关键字:重载 操作符      更新时间:2023-10-16
#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;
}