我认为这个问题非常简单,可以用“运算符自动过载哪个运算符?”这几个词来缩小。 我已经知道发生了什么,但我现在错过了一些能够解释我的详细信息为什么它正在发挥作用。
不幸的是我没有在Stroustrup的C ++参考资料中找到任何有用的东西,我很确定你们中的某些人可以帮我弄清楚发生了什么。 让我们打开讨论:这里有一个类似我正在看的代码的快照:
class MyPair : public pair<string,string>
{
public:
MyPair()
{
pair<string,string>();
}
};
到目前为止,没有任何奇怪的内容,正如线程中广泛讨论的那样 What are all the member-functions created by compiler for a class? Does that happen all the time? 编译器将自动生成默认版本的复制构造函数 复制赋值运算符和析构函数,但不会生成默认构造函数只是因为我重新定义了自己的。 感谢编译器,我将能够在创建时使用默认的复制构造函数分配一个新对象,并在创建对象后立即使用赋值运算符,如下所示:
//default copy constructor
MyPair mypair1 = mypair;
MyPair mypair2;
//default assignment operator
mypair2 = mypair1
到目前为止,一切都按设计工作。 想象一下,由于某种未知的原因,我希望将一个字符串对象分配给MyPair对象,如下所示:
int main()
{
pair<string,string> aPair;
MyPair mypair;
string mystring("test");
//ERROR
mypair = mystring;
return 0;
}
在我测试这行代码之前,我曾期待编译器会抱怨(因为我没有向它提供 operator = 的任何显式重载,所以本身就是无法为创建的对象分配字符串),实际上它给我一个非常自我解释的错误,如:
test.cpp:36:13: error: no match for ‘operator=’ in ‘mypair = mystring’
test.cpp:36:13: note: candidate is:
test.cpp:7:7: note: MyPair& MyPair::operator=(const MyPair&)
现在,想象一下通过添加以下方法来完成MyPair类:
MyPair(const string& astring)
{
pair<string,string>(astring,string());
}
突然,代码开始编译,不再给出任何类型的错误。 在我看来,上面的方法似乎为编译器提供了某种聪明之处;它开始产生缺失的 MyPair&amp; MyPair :: operator =(const string&amp; s)。
我不得不承认这听起来真的很棒,但我无法理解它究竟发生的原因。 这意味着对于我在MyPair中使用的每个额外构造函数,复制器将生成一个额外的重载 operator = ,这使得我的类可复制可分配到指定的引用只是因为那个?
答案 0 :(得分:2)
MyPair(const string& astring)
是一个隐式转换构造函数。您的string
首先用于创建新的MyPair
,然后将其分配给您的对象。您可以通过将其标记为显式来禁止此行为:
explicit MyPair(const string& astring)
这可以防止隐式转换,所以
mypair = mystring;
是非法的,而
mypair = MyPair(mystring);
仍然有效。
答案 1 :(得分:1)
告诉您初始化基类成员的方式不正确。
MyPair()
{
pair<string,string>();
}
应改为:
MyPair() : pair<string, string>()
{
}
和
MyPair(const string& astring)
{
pair<string,string>(astring,string());
}
应改为:
MyPair(const string& astring) : pair<string, string>(astring, string())
{
}
至于分配工作的原因,使用构造函数创建临时的MyPair
,并将其用作赋值运算符的参数。