简体   繁体   中英

Copying class by constructor in C++

I've got a class person that include name, ID and static constructor. I defined a copy constructor that copy only name to defining person. Does anyone know why ID and counter aren't shown correctly after defining per_2? Do I have to define ID somehow that it's an exception and can't be copied?

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

The default constructor is not called when you use the copy constuctor, but you can add a converting constructor that creates a person from a name and delegate to that constructor in other constructors. I suggest delete ing the copy constructor and replacing it with a default move constructor though. You probably don't want two person s with the same ID.

Example:

#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)
{}

You can replace the separate default constructor and the converting constructor with one constructor by using a default value for name:

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

The default constructor is not executed when the copy constructor is called. As a result, ID is not initialized in per_2 .

You'll need to duplicate the code from the default constructor to assign the next available ID (or add a private member function to do that, and have both constructors call it).

When you invoke the copy constructor, the default constructor is ignored. Both an individual person's ID as well as person::counter are only altered by the default constructor, so this means that they will be ignored when the copy constructor is called. Your program is allocating memory for per_2's name and ID, which have dummy values to begin with, then the name is overwritten to be a copy of per_1's name and it's done. In your copy constructor, you also need to specify what the ID should be as well as person::counter or no changes will be made. You could add these two functionalities into a helper method that is called by both the default constructor and the copy constructor for cleaner code, if you wish.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM