Копирование класса конструктором в C ++ - PullRequest
1 голос
/ 06 апреля 2020

У меня есть ученик класса, который включает имя, идентификатор и конструктор stati c. Я определил конструктор копирования, который копирует только имя определяющему человеку. Кто-нибудь знает, почему идентификатор и счетчик не отображаются правильно после определения per_2? Нужно ли как-то определять идентификатор, чтобы он был исключением и не мог быть скопирован?

#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;
}

Ответы [ 3 ]

2 голосов
/ 06 апреля 2020

Конструктор по умолчанию не вызывается при использовании конструктора копирования, но вы можете добавить конвертирующий конструктор, который создает person из name, и делегировать этому конструктору другие конструкторы. Я предлагаю delete использовать конструктор копирования и заменить его на default конструктор перемещения. Возможно, вам не нужны два person с одинаковым идентификатором.

Пример:

#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)
{}
1 голос
/ 06 апреля 2020

Конструктор по умолчанию не выполняется, когда вызывается конструктор копирования. В результате ID не инициализируется в per_2.

. Вам нужно будет продублировать код из конструктора по умолчанию, чтобы назначить следующий доступный идентификатор (или добавить для этого частную функцию-член, и пусть оба конструктора его называют).

0 голосов
/ 06 апреля 2020

Когда вы вызываете конструктор копирования, конструктор по умолчанию игнорируется. И идентификатор отдельного человека, а также person::counter изменяются только конструктором по умолчанию, поэтому это означает, что они будут игнорироваться при вызове конструктора копирования. Ваша программа выделяет память для имени и идентификатора per_2, которые для начала имеют фиктивные значения, затем имя перезаписывается, чтобы стать копией имени per_1, и все готово. В конструкторе копирования вам также нужно указать, каким должен быть идентификатор, а также person::counter, иначе изменения не будут сделаны. Вы можете добавить эти две функции в вспомогательный метод, который вызывается как конструктором по умолчанию, так и конструктором копирования для более чистого кода, если вы используете sh.

...