Let's assume I have following situation:
class NamedObject{
public:
NamedObject(const std::string &name):name_{std::move(name)}{}
private:
const std::string name_;
}
class Person: public NamedObject{
public:
Person(const std::string &name, int age): NamedObject(name), age_{age}{}
private:
int age_;
}
I want to create a "copy constructor" where I copy all members from Person
but change the name (for whatever reason).
class Person: public NamedObject{
public:
Person(const std::string &name, int age): NamedObject(name), age_{age}{}
Person(const std::string &newName, const Person &other): NamedObject(name){
age_ = other.age;
}
private:
int age_;
}
Now assume I have not only one attribute like age
but many attributes and they are changed a lot during development. Is it somehow easily possible to create a function like Person(const std::string &newName, const Person &other)
without manually copying all attributes like age_ = other.age;
. The idea is that during development I do not have to always recall to change this constructor if I add a new attribute.
Please note that I cannot simply change the name because it is const
.
You could define an assignment operator on NamedObject
that does nothing. Then you would be able to use *this = other
in the "copy constructor":
class NamedObject{
public:
NamedObject(const std::string &name):name_{name}{}
NamedObject &operator= (const NamedObject &) {
return *this;
}
const std::string name_;
};
class Person: public NamedObject{
public:
Person(const std::string &name, int age): NamedObject(name), age_{age}{}
Person(const std::string &newName, const Person &other): NamedObject(newName){
*this = other;
}
int age_;
};
Live example: https://onlinegdb.com/rJ4J5oy3M
Why it works:
C++ will automatically define a copy assignment operator for eligible classes (check the following link for details on what eligible means). From cppreference:
If the implicitly-declared copy assignment operator is neither deleted nor trivial, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used. For union types, the implicitly-defined copy assignment copies the object representation (as by std::memmove). For non-union class types (class and struct), the operator performs member-wise copy assignment of the object's bases and non-static members, in their initialization order, using built-in assignment for the scalars and copy assignment operator for class types.
Thus, for your example the implicitly defined copy assignment operator (the one that is called when we do *this = other;
) will be defined as follows:
NamedObject
to copy the base class (which we defined to do nothing, so it won't copy name_
),age_
and any additional member you add to the class.