I know there are many posts on the subject, but I couldn't find any to fully answer my questions.
Say I have a Base class and a Derived class, which I implemented a CCtor and an assignment operator for it, something like the following:
class Base {
char * name;
....
Base(const Base& other) :name(nullptr) { *this = other }
void operator=(const Base& other) { ... Deep copy of name }
}
class Derived : public Base {
....
Derived(const Derived& other) { *this = other ; }
void operator=(const Derived& other) {
Base::operator=(other);
.....
}
Now I have some questions about this design.
Edit: Just to clarify, the design is what I was given in my project .. I have pointers so I have to use a deep copy .
Is this the right design for the situation?
No, not usually. The more idiomatic approach is to stop manually managing memory like char* name
and use std::string
or another type that does the right thing:
Class Base {
std::string name;
....
Base(const Base& other) = default;
Base& operator=(const Base& other) = default;
};
(Note that assignment operators should return a reference to the class, not void
).
Or encapsulate the memory management in a class design specifically for that purpose (but std::string
already is that type).
If you really really need to do it the dumb error-prone way, then implement your copy constructor to do copying:
Base(const Base& other) { / * deep copy of name */ }
Then implement assignment as copy-and-swap:
Base& operator=(const Base& other)
{
Base tmp(other);
this->swap(tmp);
return *this;
}
This means you need a cheap, non-throwing swap(Base&)
member function.
In any case the derived type copy constructor is just silly. You have a correct copy constructor for the base class so it should be:
Derived(const Derived& other) : Base(other) { }
And the assignment can use the base assignment:
Derived& operator=(const Derived& other)
{
Base::operator=(other);
return *this;
}
But writing these manually is unnecessary, you can just default its copy operations which will Do The Right Thing anyway:
class Derived : public Base {
public:
Derived(const Derived&) = default;
Derived& operator=(const Derived& ) = default;
If i have a third class, between the base and the derived class, but it only contains primitive types, where shoud I copy them ? E.G. use the default assignment operator of the second class ? build a new one? only copy them on the third level ?
You should define the copy constructor and assignment operator of that class using = default
as well. Once you've made Base
safe to copy with correct behaviour, composing other classes to use it is trivial. The default behaviour will Do The Right Thing. You only need to define those operations manually if you need special treatment for something like dynamically-allocated memory that isn't being correctly managed by an RAII type.
I could similary call the base class CCtor inside the derived class CCtor, instead of the assignment operator. What's the difference?
If you want to copy construct then use the copy constructor, not assignment. Use the right function for the job.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With