在 C++ 中通过构造函数复制类

Posted

技术标签:

【中文标题】在 C++ 中通过构造函数复制类【英文标题】:Copying class by constructor in C++ 【发布时间】:2020-04-05 22:41:04 【问题描述】:

我有一个班级人员,包括姓名、ID 和静态构造函数。我定义了一个复制构造函数,它只将名称复制到定义人员。有谁知道为什么定义 per_2 后 ID 和 counter 没有正确显示?我是否必须以某种方式定义 ID 以使其异常且无法复制?

#include<iostream>
#include<string>

using namespace std;

class person 
  public:
    string name;
  int ID;
  static int counter;
  person();
  ~person();
  person(const person & );
;

int person::counter = 0;
person::person() 
  counter++;
  ID = counter;

person::~person() 


person::person(const person & obj) 
  this - > name = obj.name; //Here I define that only name is supposed to be copied


int main() 
  person per_1;
  per_1.name = "John";

  cout << per_1.ID << endl; // It gives 1 and it's fine.
  cout << person::counter << endl; // So does it.

  person per_2 = per_1; // Here I copy class and give per_1's variables to per_2.

  cout << per_2.ID << endl; // Here I expect 2, because constructor incremented counter and assigned it to per_2.ID while it gives -84534283.
  cout << person::counter << endl; // There is still 1, despite incrementing counter in constructor.

  system("Pause");
  return 0;

【问题讨论】:

@Marcios216 此问题仍列为未解决。没有任何答案有助于解决您遇到的问题吗? 【参考方案1】:

当您使用复制构造函数时,不会调用默认构造函数,但您可以添加一个转换构造函数,该构造函数从 name 创建一个 person 并在其他构造函数中委托给该构造函数。我建议 deleteing 复制构造函数并将其替换为 default 移动构造函数。您可能不希望两个具有相同 ID 的 persons。

例子:

#include <iostream>

class person 
public:
    int ID;
    std::string name;   
    static int counter;

    person();                             // default ctor
    explicit person(const std::string&);  // converting ctor
    person(const person &) = delete;      // copy ctor deleted to not get two persons
                                          // with the same ID
    person(person&&) = default;           // move ctor
;

int person::counter = 0;

person::person() :
    person("")                             // delegate


person::person(const std::string& Name) :  // colon starts the member initializer list
    ID(++counter),
    name(Name)

您可以通过使用名称的默认值将单独的默认构造函数和转换构造函数替换为一个构造函数:

person(const std::string& Name = ) :
    ID(++counter),
    name(Name)

【讨论】:

【参考方案2】:

调用复制构造函数时不执行默认构造函数。因此,ID 未在 per_2 中初始化。

您需要从默认构造函数复制代码以分配下一个可用 ID(或添加一个私有成员函数来执行此操作,并让两个构造函数都调用它)。

【讨论】:

也许提到委托构造函数? 也许听起来很蠢,但是如果我先初始化 per_2(应该执行默认构造函数)然后在下一行写 per_2=per_1 呢? @Macios216 由于您尚未定义复制赋值运算符,因此将使用默认值,它将覆盖ID【参考方案3】:

当您调用复制构造函数时,默认构造函数将被忽略。个人 ID 和 person::counter 都仅由默认构造函数更改,因此这意味着在调用复制构造函数时它们将被忽略。您的程序正在为 per_2 的名称和 ID 分配内存,它们以虚拟值开头,然后将名称覆盖为 per_1 名称的副本,然后就完成了。在您的复制构造函数中,您还需要指定 ID 应该是什么以及person::counter,否则将不会进行任何更改。如果您愿意,您可以将这两个功能添加到由默认构造函数和复制构造函数调用的辅助方法中,以获得更简洁的代码。

【讨论】:

以上是关于在 C++ 中通过构造函数复制类的主要内容,如果未能解决你的问题,请参考以下文章

为啥我们需要一个默认构造函数来在 C++ 中通过引用传递一个对象?

虚函数总结

c++ 类的复制函数

C++中复制构造函数被调用的三种情况

c++,类的对象作为形参时一定会调用复制构造函数吗?

复制构造函数 C++ 没有正确复制指针