考虑以下示例:
#include <iostream>
using std::cout;
using std::endl;
class CBox
{
public:
CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0) :
m_Length {lv}, m_Width {wv}, m_Height {hv}
{
cout << "Constructor called" << endl;
}
//CBox& operator=(double)
//{
// cout << "Assignment operator called" << endl;
// return *this;
//}
double volume() const { return m_Length* m_Width* m_Height; }
private:
double m_Length;
double m_Width;
double m_Height;
};
int main()
{
CBox box {1.0, 1.0, 1.0}; // no need for initializer list, but put it anyway
box = 2.0; // why is this calling constructor again ?!
cout << box.volume() << endl; // prints 2
}
Run Code Online (Sandbox Code Playgroud)
请注意,我故意注释掉了重载的赋值运算符.
执行此程序会产生以下输出:
Constructor called
Constructor called
2
Run Code Online (Sandbox Code Playgroud)
我注意到,即使box对象已经初始化,下一个语句也是故意再次调用构造函数.那是什么意思?
我知道这可以通过explicit关键字来阻止,所以构造函数将是:
explicit CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0) :
m_Length {lv}, m_Width {wv}, m_Height {hv}
{
cout << "Constructor called" << endl;
}
Run Code Online (Sandbox Code Playgroud)
但我宁愿期望它会影响像这样的结构:
CBox box = 2.0;
Run Code Online (Sandbox Code Playgroud)
当然,当我取消注释重载赋值运算符时,它优先于构造函数.
Mil*_*nek 17
没有隐含CBox::operator=(double),所以box = 2.0;必须创建一个临时CBox对象.它相当于box = CBox(2.0);.
使你的构造explicit不允许从隐式转换double到CBox,所以没有相应的赋值操作符存在,你会得到一个编译错误.
两者之间有很大的不同
CBox box = 2.0
Run Code Online (Sandbox Code Playgroud)
和
box = 2.0
Run Code Online (Sandbox Code Playgroud)
第一个相当于
CBox box = CBox(2.0)
Run Code Online (Sandbox Code Playgroud)
而第二个相当于
box.operator=(2.0)
Run Code Online (Sandbox Code Playgroud)
由于构造函数的参数具有默认值,因此这相当于定义3个不同的构造函数:
CBox(double, double, double)
CBox(double, double) // the third arguments gets default value
CBox(double) // second and third arguments gets default values
Run Code Online (Sandbox Code Playgroud)
因此,使用单个显式double调用构造函数将调用构造函数,并将为第二个和第三个参数提供默认值.而现在真正的神秘:为什么调用operator=最终结果调用构造函数?
由于您没有明确定义operator=,编译器将自动生成一个赋值运算符,该运算符将另一个CBox作为其单个参数; 这将成为论证的副本.
当您尝试将任何内容分配给CBox对象时,编译器将尝试调用operator=(const CBox&); 既然你提供的是a double而不是a CBox,编译器会尝试将double转换CBox为多种可能的方式之一:
所以,最终这段代码:
box = 2.0
Run Code Online (Sandbox Code Playgroud)
将被翻译为:
box.operator=(Cbox(2.0))
Run Code Online (Sandbox Code Playgroud)