【问题标题】:Copy Constructor called unexpectedly意外调用了复制构造函数
【发布时间】:2021-11-08 01:25:17
【问题描述】:

我是 C++ 编程的新手。我正在使用 Visual Studio Code,我的代码:

#include <iostream>
using namespace std;

class Calculator;

class Complex
{
    float a, b;
    string Operation;
    string name;

    friend class Calculator;

public:
    Complex(float, float, string, string);
    Complex(float);
    Complex();
    Complex(Complex &, string);

    void PrintComp(string op = "None")
    {
        if (op != "None" && name != "None")
        {
            cout << "\nBy " << op << " of z1 and z2:\n"
                 << name << " = " << a << " + " << b << "i\n";
        }
        else if (name != "None")
        {
            cout << name << " = " << a << " + " << b << "i\n";
        }
        else
        {
            cout << a << " + " << b << "i\n";
        }
    }
};

Complex ::Complex(float x, float y, string givnname = "None", string operation = "None")
{
    a = x;
    b = y;
    name = givnname;
    PrintComp(operation);
}
Complex ::Complex(float x)
{
    a = x;
    b = 0;
}
Complex ::Complex()
{
    a = 0;
    b = 0;
}
Complex::Complex(Complex &obj, string givnname="None")
{
    a = obj.a;
    b = obj.b;
    name = givnname;
    cout << "Copy Cons called!"<< endl;
    PrintComp();
}

class Calculator
{
public:
    float SumRealComp(Complex const&, Complex const&);
    float SumImgComp(Complex const&, Complex const&);
};

float Calculator ::SumRealComp(Complex const &obj1, Complex const & obj2)
{
    return (obj1.a + obj2.a);
}
float Calculator ::SumImgComp(Complex const & obj1, Complex const & obj2)
{
    return (obj1.b + obj2.b);
}

int main()
{
    Complex z1(3, 5, "z1"), z2(4, 4, "z2");

    Calculator calc;

    Complex z3(calc.SumRealComp(z1, z2), calc.SumImgComp(z1, z2), "z3", "Sum");

    Complex z4(z1, "z4");

    return 0;
}

根据上面的代码,我最后使用的是复制构造函数,但是 复制构造函数在每个对象的形成时被调用。即使两者的参数不同。为什么会这样? 我正在向here 学习。
感谢我的代码中的每一个建议。
谢谢!

【问题讨论】:

  • Complex(Complex &amp;, string); 不是复制构造函数; Complex(Complex const &amp;); 是复制构造函数的预期签名,请参阅 Copy constructors
  • @RichardCritten,Complex(Complex&amp;, string);的第二个参数有一个默认值,可以是一个复制构造函数。
  • @GhasemRamezani 但第一个参数是非常量引用 - 这也是不寻常的,因为它不能绑定到临时。作为一种教学/学习实践,这是糟糕的代码。
  • @RichardCritten, X::X 是一个复制构造函数,如果它的第一个参数是X&amp;X const&amp;X volatile&amp;X const volatile&amp; 类型。 eel.is/c++draft/class.copy.ctor
  • @GhasemRamezani 同意 - 但X const&amp; 以外的任何其他人都不应该真正参与介绍复制构造函数的练习,因为应该如何使用其他形式要先进得多。

标签: c++ copy-constructor


【解决方案1】:

您将在这些函数上获取Complex 对象的副本:

Calculator::SumRealComp(Complex, Complex);
Calculator::SumImgComp(Complex, Complex);

因此,每次调用这些函数时,您都会获取Complex 对象的两个副本。您可以传递 Complex const&amp; 对象以避免复制:

Calculator::SumRealComp(Complex const&, Complex const&);
Calculator::SumImgComp(Complex const&, Complex const&);

复制构造函数

复制构造函数是Class Special Member Functions之一,每当我们尝试获取对象的副本时都会调用:

class X;
void f(X); 

X x;
f(x); // <--- Here

X another(x); // <--- Here
X yet_another = x; // <--- And here

在注释部分,我们可以调用X 复制构造函数。复制构造函数可以定义为以下签名:

X::X(X&);
X::X(X const&);
X::X(X volatile&);
X::X(X const volatile&);

注意:与您的代码一样,我们可以在复制构造函数中添加其他参数,但它们具有默认值)。
注意:有关更多信息:阅读Bjarne Stroustrup 的“C++ 编程语言”第 17 章。


这与您的问题无关,是我对您的代码的建议,如果您不喜欢它,您可以跳过(或编辑并删除它)

一些代码审查建议:

  1. 停止使用using namespace std;,这可能会导致未定义的行为并给您带来困难的调试时间:Why is "using namespace std;" considered bad practice?
  2. 如果没有必要,不要使复制构造函数签名复杂化。您可以按如下方式重写复制构造函数:
Complex::Complex(Complex const& obj)
    : a(obj.a)
    , b(obj.b)
    , name(obj.name)
{
    cout << "Copy Cons called!" << endl;
    PrintComp();
}
  1. 使用成员初始化列表初始化成员变量。

【讨论】:

  • 感谢@GhasemRamezani 您的所有建议都对我很有帮助。但是我无法理解您制作的复制构造函数的语法。你能澄清一下吗?
  • 这个我没看懂: : a(obj.a) , b(obj.b) , name(obj.name)
  • @AdityaSoni,好好读一下Book,这些都是基础知识。
  • 其实我正处于学习阶段。所以,我应该完成我的教程,然后这个语法应该很清楚。我正在 YouTube 上向 CodeWithHarry 学习。我向他学习了python,他是一位非常好的老师。所以,我应该耐心等待涵盖这件事的那部分。感谢您为让我解决此问题所做的一切努力。如果您愿意,请支持我的问题。
猜你喜欢
  • 1970-01-01
  • 2020-07-04
  • 2015-06-16
  • 1970-01-01
  • 1970-01-01
  • 2021-05-14
  • 2018-10-17
  • 1970-01-01
  • 2017-02-08
相关资源
最近更新 更多