为什么在没有赋值运算符的情况下调用转换构造函数
Why is conversion constructor called in absense of assignment operator?
今天我的问题是,为什么在没有用户提供的赋值运算符的情况下调用构造函数?我知道构造函数和赋值运算符在=
符号方面的区别。如果对象在该行之前不存在,则隐式调用构造函数。
std::string name = "Bjarne"; // implicit constructor
如果对象在该行之前已经存在,则调用赋值运算符。
std::string name;
name = "Bjarne"; // assignment operator
现在我有一个class Number
,它是一个标记的并集。它只是一个数字,意味着int
或float
。我定义了多个转换构造函数,使用户可以轻松地将值隐式分配给Number
。我希望他们在这种情况下被召唤:
Number num1 = 8;
为了确定何时调用哪个构造函数,我将print语句放在构造函数的主体中。
#include <cstdlib>
#include <iostream>
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::ostream;
/* Unions can be anonymous (unnamed).
* This form is used when nesting a union inside a struct or class that contains an extra data member
* to indicate what the union contains.
* This arrangement is called a tagged union (or managed union).
* It can be used as a "polymorphic" class which can be several things at once, for example to create an array
* of different data types.
*/
class Number {
friend ostream& operator<<(ostream& os, Number& num);
public:
Number(int i = 0) : DATA_TYPE(INTEGER), i(i) { cerr << "Number(" << i << ")n"; }
Number(unsigned int u) : DATA_TYPE(INTEGER), i(static_cast<int>(u)) { cerr << "Number((signed) " << i << ")n"; }
Number(float f) : DATA_TYPE(FLOAT), f(f) { cerr << "Number(" << f << ")n"; }
Number(double d) : DATA_TYPE(FLOAT), f(static_cast<float>(d)) { cerr << "Number((float) " << f << ")n"; }
Number(const Number& rhs) : DATA_TYPE(rhs.DATA_TYPE), i(rhs.i) { cerr << "Number((Number) " << *this << ")n"; }
private:
enum data_type { INTEGER, FLOAT } DATA_TYPE;
union {
int i;
float f;
};
};
ostream& operator<<(ostream& os, Number& num)
{
switch (num.DATA_TYPE) {
case Number::INTEGER:
cout << num.i;
break;
case Number::FLOAT:
cout << num.f;
break;
default:
cout << 0;
break;
}
return os;
}
int main()
{
Number num1 = 5; // conversion constructor
cout << num1 << endl;
num1 = 12.5;
cout << num1 << endl;
return EXIT_SUCCESS;
}
当我运行此代码时,它会为我产生意外的输出:
Number(5)
5
Number((float) 12.5)
12.5
我看到当Number num1
初始化时,会调用以int
为参数的构造函数。然后我打印num1
的值。然后在下一行,似乎调用了以double
为参数的构造函数。这很奇怪。在这行之前,num1
已经作为一个对象存在。所以它应该在逻辑上调用赋值运算符。我没有定义赋值运算符,所以我认为编译器生成的赋值运算符将被调用。
我想知道,在没有用户提供的赋值运算符的情况下,当我这样做时会发生什么?num1 = something;
是调用编译器提供的默认赋值运算符,还是调用构造函数?当对已经存在的对象调用构造函数时会发生什么?那个物体被"重建"了吗?那么,在这种情况下到底会发生什么呢?
我想知道,在没有用户提供的赋值运算符的情况下,当我执行此
num1 = something;
时会发生什么?
num1 = 12.5;
调用隐式CCD_ 15。
因此,从double
构造一个临时数字。
是调用编译器提供的默认赋值运算符,还是调用构造函数?
两者都有。构造函数是为临时对象而不是现有对象调用的。
当对已经存在的对象调用构造函数时会发生什么?那个物体被"重建"了吗?那么,在这种情况下到底会发生什么呢?
您不能调用现有对象上的构造函数。你能做的最接近的事情就是放置新的。
多亏了Jarod42,我才弄明白。因此,正如他所建议的,在=
的右侧无形地构建了一个临时Number
对象,然后调用赋值运算符,在该行的末尾,临时对象被销毁。
我将以下代码添加到Number
类中,以实际查看发生了什么
Number& operator=(const Number& rhs)
{
cerr << "operator=(const Number&)" << endl;
return *this;
}
~Number() { cerr << "~Number()" << endl; }
有了这个main()
功能
int main()
{
Number num1 = 5;
num1 = 12.5;
cout << endl;
Number num2 = 8;
num1 = num2;
return EXIT_SUCCESS;
}
产生以下输出:
Number(5)
Number((float) 12.5)
operator=(const Number&)
~Number()
Number(8)
operator=(const Number&)
~Number()
~Number()
- 如果 std::vector::clear() 不是静态的,如何在没有实例的情况下调用它?
- C++ - 如何在不调用其属性的情况下调用类?
- C++ 在不释放内存的情况下调用析构函数
- Python在不引用类名的情况下调用类函数
- 为什么在这种情况下调用非常量右值移动构造函数?
- 是否可以在没有显式专用化的情况下调用可变参数模板函数?
- 使用按引用调用时,不能在没有对象的情况下调用成员函数 const
- 您可以在不调用构造函数的情况下调用攻击器吗?
- 命名空间:不能在没有对象的情况下调用成员函数
- 哪些语言将在没有显式桥接的情况下调用C++
- 如何在不重新索引顶点的情况下调用"boost::remove_vertex"?
- C :在没有对象实例的情况下调用非静态成员函数
- 在不实例化的情况下调用不同派生类的虚拟方法
- C 如何在没有错误的情况下调用void函数
- 在MSVC上的数组初始化期间,destructor在不复制或移动构造方的情况下调用
- 在不指定实例化的情况下调用类模板的静态方法的方法
- 为什么INVOKE总是取消引用数据成员,而不是在可能的情况下调用
- 是否可以在不实例化派生类的情况下调用该类的虚拟函数
- 无法在没有对象的情况下调用成员函数(尽管我相信我确实初始化了它)
- 为什么在没有赋值运算符的情况下调用转换构造函数