为什么在分配发生时调用参数化构造函数?
Why Paramaterized constructor called when assignment is happening?
我的问题是针对最后一个陈述,即 return 0;
之前
为什么在我们尝试将 int 值分配给对象时调用 parametrize 构造函数。
我的一段代码:
#include<iostream>
using namespace std;
class Test {
private:
int i;
public:
Test(int s=0):i(s) {
cout<<"param ctor: "<<i<<endl;
}
};
int main()
{
Test a; //param ctor called
Test b(5); //param ctor called
//b(a); //error as we have not implemented copy ctor
b=a; //compiler provided assignment opr. called
b=100; //why param ctor called for this.??
return 0;
}
输出:
param ctor: 0
param ctor: 5
param ctor: 100
我不确定,但是,
我开始知道编译器首先搜索匹配的函数调用..
b=100;
即overloaded assignment operator function
for class A
以 int 作为参数
当它找不到任何合适的匹配项时,它会直接调用参数化构造函数。
它依次完成剩余的分配工作。
如果我错了或遗漏了任何细节,请随时纠正我。
原因很简单:everyclassX
有一个拷贝构造函数(一个取X
的构造函数)和一个拷贝赋值运算符(取 X
的赋值运算符)。如果您不自己声明这些,编译器会隐式地为您声明它们。在某些情况下,它们被定义为已删除(这意味着使用它们是错误的),但它们始终存在。
所以当你这样做时:
b = 100;
有效翻译为:
b.operator=(100)
并搜索 operator=
的最佳匹配重载。实际上只有一个重载:隐式声明的复制赋值运算符 Test& Test::operator=(const Test &)
,因此编译器会检查它是否可以将参数 100
转换为赋值运算符的参数类型 const Test &
。事实证明它可以,多亏了转换构造函数 Test::Test(int)
,所以这就是最终调用的内容。
如果你想禁用这种行为,你可以将构造函数标记为explicit
。这将防止它被用于隐式转换,例如将 100
转换为赋值运算符参数的类型。
您的构造函数 Test(int s=0)
可用作从 int
到 Test
的转换运算符。当计算 b = 100
时,100 被转换为 Test
,然后调用默认赋值运算符。
当您执行 b=100
时,基本上发生的是编译器生成 b.operator=(Test(100))
您看到的构造函数调用来自 Test(100)
。
如果您创建构造函数 explicit
,则编译器无法使用构造函数将 int
值隐式转换为 Test
对象,您会得到一个错误。
我的问题是针对最后一个陈述,即 return 0;
为什么在我们尝试将 int 值分配给对象时调用 parametrize 构造函数。
我的一段代码:
#include<iostream>
using namespace std;
class Test {
private:
int i;
public:
Test(int s=0):i(s) {
cout<<"param ctor: "<<i<<endl;
}
};
int main()
{
Test a; //param ctor called
Test b(5); //param ctor called
//b(a); //error as we have not implemented copy ctor
b=a; //compiler provided assignment opr. called
b=100; //why param ctor called for this.??
return 0;
}
输出:
param ctor: 0
param ctor: 5
param ctor: 100
我不确定,但是,
我开始知道编译器首先搜索匹配的函数调用..
b=100;
即overloaded assignment operator function
for class A
以 int 作为参数
当它找不到任何合适的匹配项时,它会直接调用参数化构造函数。
它依次完成剩余的分配工作。
如果我错了或遗漏了任何细节,请随时纠正我。
原因很简单:everyclassX
有一个拷贝构造函数(一个取X
的构造函数)和一个拷贝赋值运算符(取 X
的赋值运算符)。如果您不自己声明这些,编译器会隐式地为您声明它们。在某些情况下,它们被定义为已删除(这意味着使用它们是错误的),但它们始终存在。
所以当你这样做时:
b = 100;
有效翻译为:
b.operator=(100)
并搜索 operator=
的最佳匹配重载。实际上只有一个重载:隐式声明的复制赋值运算符 Test& Test::operator=(const Test &)
,因此编译器会检查它是否可以将参数 100
转换为赋值运算符的参数类型 const Test &
。事实证明它可以,多亏了转换构造函数 Test::Test(int)
,所以这就是最终调用的内容。
如果你想禁用这种行为,你可以将构造函数标记为explicit
。这将防止它被用于隐式转换,例如将 100
转换为赋值运算符参数的类型。
您的构造函数 Test(int s=0)
可用作从 int
到 Test
的转换运算符。当计算 b = 100
时,100 被转换为 Test
,然后调用默认赋值运算符。
当您执行 b=100
时,基本上发生的是编译器生成 b.operator=(Test(100))
您看到的构造函数调用来自 Test(100)
。
如果您创建构造函数 explicit
,则编译器无法使用构造函数将 int
值隐式转换为 Test
对象,您会得到一个错误。