简体   繁体   中英

Copy constructor for more structures in class C++

i'm doing program for people register.

I have class CRegister:

int personCount
int personSize
Person ** persons

Struct Person

char * name
char * surname
Places ** oldPlaces // here is former residence of this person

and struct oldPlaces

char date[11]
char * street
char * city

In every class/struct i have constructor which allocated empty memory for instance and metods add which added people or place.

The problem is how can implement copy constructor?

I have this for CRegister

CRegister::CRegister(const CRegister& b):personCount(b.personCount), personSize(b.personSize){
 persons = new Person*[b.personSize];
 personCount = 0;
 personSize = b.personSize;
 for (int i = 0; i < personSize; i++){
     persons[i] = new Person();
     persons[i].addPerson(b.persons[i]->id, b.persons[i]->name, b.persons[i]->surname);
 }

But i want to copy oldPlaces also...

Thanks for any advice.

You should create a copy constructor for Person as well and use it for each person in the array.

for (int i = 0; i < personSize; i++)
    persons[i] = new Person(*b.persons[i]);

And copy the places in it:

Person::Person(const Person &b) {
    ...
    // (Note that you will have to do a deep copy for the strings here as well)
    oldPlaces = new Places *[oldPlacesCount];
    for (int i = 0; i < oldPlacesCount; i++)
        oldPlaces[i] = new Places(*b.oldPlaces[i]);
}

And then maybe also create a copy constructor for Places etc.

EDIT: Yes, and you need to add oldPlacesCount .

First, the problem more or less solves itself if you use std::string and std::vector . If you insist on using pointers, you'll have to do a deep copy yourself (along with assignment and destructors). In each object, you'll have to visit all of the pointers, "cloning" the sub-objects. And you'll have to handle the case where the allocations fail, which could leave objects of type Person and Places in an inconsistent state. Getting this right requires a lot of code, and a high degree of C++ expertise. You don't want to go that route. (Writing a C++ class which has two raw pointers to dynamically allocated memory can be very complicated. Using shared_ptr or scoped_ptr makes it a lot simpler, but still not as simple as using vector and string .)

EDIT:

Just to make it clear what is involved, here's what's needed for Place , if you don't use the standard library:

struct Place
{
    char date[11];
    char* street;
    char* city;

    Place()
        : street( NULL )
        , city( NULL )
    {
        memset( date, '\0', sizeof( date ) );
    }

    Place( Place const& other )
        : street( NULL )
        , city( NULL )
    {
        memcpy( date, other.date, sizeof( date ) )
        try {
            street = new char[ strlen( other.street ) + 1 ];
            strcpy( street, other.street );
            city = new char[ strlen( other.city ) + 1 ];
            strcpy( city, other.city );
        } catch ( ... ) {
            delete [] street;
            delete [] city;
            throw;
        }
    }

    Place& operator=( Place const& other )
    {
        Place tmp( other );
        memcpy( date, other.date, sizeof( date ) );
        std::swap( street, other.street );
        std::swap( city, other.city );
        return *this;
    }

    ~Place()
    {
        delete [] street;
        delete [] city;
    }
};

Person is even more complicated, because you have to initialize the entire array oldPlaces to NULL , then to the copies in a try block, and delete them if anything goes wrong.

In practice, the first thing anyone with any experience in C++ would do, if for some reason he or she couldn't use the standard library, would be to implement a (probably simplified) version of std::string and std::vector , and use them. Try blocks like in the copy constructor above are typically an indication that the programmer doesn't really understand C++. All allocations and frees in code like the above would be wrapped in a smaller, more primitive classes, each of which managed at most one dynamically allocated resource. Thus, even in keeping very close to what you have written, one would probably develop a StringPtr class, and use that in Person, etc. Similarly, one would use an array of Person and an array of Place , rather than arrays of pointers.

I don't know to what degree your structures have been imposed by your teacher, but this is not the way one programs in C++.

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