派生 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 的任何其他成员使用复制赋值运算符。
假设我有以下情况:
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 的任何其他成员使用复制赋值运算符。