0

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*?

ZethGaming
  • 17
  • 3
  • You don't have an assignment operator overload. Since you are allocating dynamically, you need that as well otherwise you will have duplicate free. And obviously `o1 = parent(name);` needs that as well. – Devolus Apr 06 '21 at 09:20
  • On top of that, `print` will crash if no username has been assigned, you you should allocate an empty string to it, in the default constructor, or you need to validate that it is not nullptr. – Devolus Apr 06 '21 at 09:23
  • @Devolus Thanks mate , it seems to be fine now , though it won't work for a derived class child with one more char* parameter, but im trying to figure it out. – ZethGaming Apr 06 '21 at 09:27
  • *"I tested this method with `int*` / `float` parameters for class and no problems"*. Which is the equivalent of `strlen(name)` for `int*`? – Jarod42 Apr 06 '21 at 12:43

1 Answers1

2

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.

Nikita Smirnov
  • 813
  • 8
  • 17
  • @ZethGaming to use it with derived classes, you should override those 3/5 methods and constructors, to handle data, which appears only in derived classes. – Nikita Smirnov Apr 06 '21 at 09:44