首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++默认构造函数

C++默认构造函数
EN

Stack Overflow用户
提问于 2011-02-01 05:24:39
回答 4查看 1.6K关注 0票数 3

我得到了以下代码的编译错误:

代码语言:javascript
复制
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)

但是,当我将复制构造函数的参数类型更改为const Complex&时,它可以工作。我在想,默认的构造函数将被2 Complex:: Complex(2.0,0.0)调用,然后复制构造函数将被调用,以创建一个具有Complex(2.0)副本的。0)。对不对?

代码语言:javascript
复制
#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();
}
EN

回答 4

Stack Overflow用户

发布于 2011-02-01 05:41:01

当你写的时候

代码语言:javascript
复制
Complex a = 2;

编译器不会使用0作为默认参数来直接调用Complex构造函数来构建a,而是会考虑是否可以将2“转换”为Complex

为了进行转换,它会找到你的Complex(re,im)版本,并可以使用它,这要归功于默认值和你没有声明构造函数explicit的事实,但之后它必须找到一种方法将这个值传递给a

这个“传输”的工具可以是一个复制构造函数。但是,可以使用Complex(re,im)构建的复杂值是临时,并且由于一些可疑的原因,在C++中不允许将临时引用作为非常数引用传递给函数。

因此,您的复制构造函数不能与临时函数一起使用,并且编译器会被卡住,因为没有办法使用2初始化a

如果您声明复制构造函数而不是接受const引用,则可以将临时函数传递给复制构造函数以初始化a,因此一切都会按您所期望的那样工作。

直接初始化a可以使用语法Complex a(2)来完成,在这种情况下不需要使用复制构造函数。

还请注意,当你使用语法Complex a = ...时,编译器必须检查使用复制构造函数是否合法,但一旦检查了合法性,编译器就不能调用它,而是使用直接初始化。换句话说,即使你需要声明你的复制构造函数,接受常量引用才能编译,编译器实际上可能会跳过这一部分,直接构建a,而不调用复制构造函数(即使复制构造函数-就像你的例子一样-有副作用)。添加这个明显疯狂的规则是为了能够在生成的代码中进行一些优化。

票数 9
EN

Stack Overflow用户

发布于 2011-02-01 05:29:45

正如您所发现的,C++中的复制构造函数需要参数的const部分才能接受常量参数。否则,您没有创建可以接受const参数的复制构造函数,而是创建了一个接受非常数Complex&作为参数的复制构造函数。

票数 1
EN

Stack Overflow用户

发布于 2011-02-01 05:30:42

您总是使用&创建一个复制结构,因此您不必复制整个对象就可以让函数使用它。创建对象副本需要时间,引用它的效率要高得多。

在任何情况下,都需要在object参数前面加上const,以便保证复制构造函数不会更改输入对象。例如:

代码语言:javascript
复制
Complex::Complex(const Complex &c)
{
        cout << "Copy constructor called " << endl;
        re = c.re;
        im = c.im;
        c.im = 'something'; // This would not work
}

致以敬意,

丹尼斯·M。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4856292

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档