派生 class 更改基础 class 的复制构造函数

copy constructor for derived class changing base class

假设我有以下情况:

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_;
}

我想创建一个 "copy constructor",我从 Person 复制所有成员,但更改名称(无论出于何种原因)。

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_;
}

现在假设我不仅有像 age 这样的一个属性,还有很多属性,并且它们在开发过程中发生了很大变化。是否可以轻松地创建一个像 Person(const std::string &newName, const Person &other) 这样的函数,而无需手动复制像 age_ = other.age; 这样的所有属性。这个想法是,在开发过程中,如果我添加一个新属性,我不必总是记得更改这个构造函数。

请注意,我不能简单地更改名称,因为它是 const

您可以在 NamedObject 上定义一个什么都不做的赋值运算符。然后你就可以在 "copy constructor":

中使用 *this = other
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_;
};

实例:https://onlinegdb.com/rJ4J5oy3M

为什么有效:

C++会自动为eligibleclasses定义一个复制赋值运算符(查看下面的link了解什么是eligible 表示)。来自 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.

因此,对于您的示例,隐式定义的复制赋值运算符(当我们执行 *this = other; 时调用的那个)将定义如下:

  • 它将使用NamedObject的复制赋值运算符复制基class(我们定义为什么都不做,所以它不会复制name_),
  • 它将对 age_ 和您添加到 class 的任何其他成员使用复制赋值运算符。