Search code examples
c++classconstructordefault-constructor

C++ Why parameterised constructor works diffrent with char*?


I recently started to work with C++ classes and everything was fine until i wanted to create a class with 'char*' parameter.

I created a default constructor, a parameterised constructor, a copy constructor and a destructor.

Tested it on int* / float parameters and it worked.

Now i tried to switch to char* and ... it didn't print my string properly;

There is the class :

class parent{

protected:

    char *username;

public:

    parent()
    {
        username=NULL;
    }


    parent(char name[10001])
    {
        int k=strlen(name);
        username = new char[k+1];
        strcpy(username, name);
    }


    parent(const parent &p1)
    {
        int k= strlen(p1.username);
        char *temp = new char[k+1];
        strcpy(temp,p1.username);

        if(username!=NULL)
            delete[] username;
        k=strlen(temp);
        username = new char[k+1];
        strcpy(username, temp);

    }

    void print()
    {
        cout << username << '\n';
    }


    ~parent()
    {
        delete[] username;
    }

};

and the problem occure when i call the constructor like this:

char name[10001]="my name";

parent o1;
o1=parent(name);
o1.print();

But it seems to be fine when i do it like this:

parent o1(name);

Again, i tested this method with int* / float parameters for class and no problems. So why isn't it working the same for char*?


Solution

  • As mentioned in comment, you should first read about The rule of three.

    If a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three.

    So you should define by yourself a copy-assignment operator. It can be implemented this way:

    parent& operator= (const parent &p1)
    {
        parent temp(p1);    // use copy constructor, you already defined
    
        std::swap(username, temp.username); // just swap our 'invalid' username with username, initialized in temp by copy constructor
    
        return *this;
        //  a destructor for temp is being called, which handles resourse deallocation
    }
    

    P.S. The rule of three has become outdated after move semantic had been introduced in C++11. Now it is also better to implement also a move-constructor and move-assignment operator, in addition to others.