提问人:carce-bo 提问时间:7/13/2022 最后编辑:carce-bo 更新时间:7/14/2022 访问量:407
从基类调用复制和赋值运算符以在 C++ 中创建继承的类实例
Calling copy and assignment operators from base class to create inherited class instances in C++
问:
我有以下类(例如):
class A {
public:
A(void) : i(0) {}
A(int val) : i(val) {}
A(const A& other) : i(other.i) {}
A& operator=(const A& other) {
i = other.i;
return *this;
}
int i;
};
class B : public A {
public:
B(void) : A(), j(0) {};
B(const B& other) : A(other), j(other.j) {}
B(int i, int j) : A(other.i), j(other.j) {}
B& operator=(const B& other) {
A::operator=(other);
j = other.j;
return *this;
}
int j;
};
我的问题是,鉴于 中的重载和复制构造函数,如果我希望能够从已经初始化的实例中创建 的实例,或者将 的现有实例分配给 的现有实例,是否有必要在 上定义另一个复制构造函数并使用以下签名?operator=
B
B
A
A
B
B
operator=
B(const A& other);
B& operator=(const A& other);
目标是能够仅使用基类信息实例化/赋值派生类实例。
PS:我正在使用 C++98 并且无法使用任何更新的标准。
答:
目标是能够仅使用基类信息实例化/赋值派生类实例。
你的目标对我来说听起来很可疑。
通常在实践中,您有两种不同的方案:
- 数据对象(不需要继承层次结构)
- 行为对象(通过继承实现相同的接口)。
数据对象(因为它们没有公共基类)实现实例化和赋值(复制构造函数和赋值运算符)。
行为对象(类层次结构中的对象)不能以泛型方式实现基类对象的赋值(如何处理派生类中存在但基类中不存在的成员变量?为它们指定默认值?保持它们不变?)。
也就是说,您应该使用与复制构造函数和赋值不同的 API,以避免混淆和隐式强制转换。
也就是说,如果您同时拥有:
B& operator=(const B&);
B& operator=(const A&);
那么当代码从 B 实例分配时,这是不明确的(因为编译器可以调用它们中的任何一个)。
您可以添加一个 .这也将使其更加明确。B::copy_common_values(const A&);
如果您尝试解决 x-y 问题,还可以查找原型设计模式。
评论
B(const &A other)
B
B
A
B
Objects A and B in my code are both data objects. B is just a data extension of A
.考虑将 A 的实例作为 B 的成员,并在这种情况下避免继承?(只是一个想法 - 我不知道它是否适用于你的问题)。
是的,你必须定义这样的东西。
B(常量 A& 其他);
这将允许构造 .这也将允许通过隐式转换为然后分配的方式进行赋值。因此,仅此一项就足够了。但是你会得到一个额外的副本。B
A
A
B
A
B
B& operator=(const A& other);
这样可以提高分配效率,因为您可以避免临时 .这还应该允许分配可以隐式转换为如下内容的内容:A
B
B
A
B b = 1;
如果你不想这样做,你可能不得不添加一些.C++98 有显式吗?这是上个千年的情况。explicit
注意:在现代 C++ 中,由于复制省略,并且您可以使用移动语义和完美的转发引用,这将更有效。
评论
explicit
评论