我使用以下代码得到编译错误:
main.cpp: In function âint main()â:
main.cpp:38: error: no matching function for call to âComplex::Complex(Complex)â
main.cpp:22: note: candidates are: Complex::Complex(Complex&)
main.cpp:15: note: Complex::Complex(double, double)
Run Code Online (Sandbox Code Playgroud)
但是当我将复制构造函数的参数类型更改为const Complex&时,它可以工作.我认为默认构造函数将使用2 Complex :: Complex(2.0,0.0)调用,然后将调用复制构造函数来创建一个带有Complex(2.0.0)的副本.不正确吗?
#include <iostream>
using namespace std;
class Complex {
double re;
double im;
public:
Complex(double re=0, double im=0);
Complex(Complex& c);
~Complex() {};
void print();
};
Complex::Complex(double re, double im)
{
cout << "Constructor called with " << re << " " << im << endl;
this->re = re;
this->im = im;
}
Complex::Complex(Complex &c)
{
cout << "Copy constructor called " << endl;
re = c.re;
im = c.im;
}
void Complex::print()
{
cout << "real = " << re << endl;
cout << "imaginary = " << im << endl;
}
int main()
{
Complex a = 2;
a.print();
Complex b = a;
b.print();
}
Run Code Online (Sandbox Code Playgroud)
当你写作
Complex a = 2;
Run Code Online (Sandbox Code Playgroud)
编译器不会直接调用Complex构造函数使用0作为构建的默认参数,a而是考虑它是否可以"转换"2到a Complex.
要进行转换,它会找到你的Complex(re,im)版本并且可以使用它,这要归功于默认值以及你没有声明构造函数的事实explicit,但是它必须找到一种方法来传递这个值a.
这种"转移"的工具可以是复制构造函数.但是,可以构建的复杂值Complex(re,im)是临时的,并且由于C++中的一些可疑原因,不允许将临时作为非const引用传递给函数.
所以你的拷贝构造函数不能和临时一起使用,编译器会被卡住,因为没有办法a用2 初始化.
如果您声明您的复制构造函数而不是接受const引用,那么临时可以传递给您的复制构造函数进行初始化a,因此一切都按预期工作.
a可以使用语法直接初始化Complex a(2),在这种情况下不需要使用复制构造函数.
还要注意,当您使用语法时Complex a = ...,编译器必须检查使用复制构造函数是否合法,这可能很奇怪,但一旦检查了该合法性,就不允许调用它并使用直接初始化.换句话说,即使你需要声明你的复制构造函数接受一个const引用仍然能够编译,编译器实际上可能会跳过该部分并直接构建a而不调用复制构造函数(即使复制构造函数 - 如你的情况一样)副作用).添加了这个显然是疯狂的规则,以便能够在生成的代码中进行一些优化.