奇怪的运算符重载行为?

时间:2013-03-04 21:39:35

标签: c++ operator-overloading

#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)重载。为什么?

4 个答案:

答案 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;

}