将子对象转换为父对象

Converting child to parent object

本文关键字:对象 转换      更新时间:2023-10-16

我将使用一个虚拟示例来描述我的问题。假设我们有这样一个架构的程序:

父类:Quadrilateral

子类:Rectangle, Rhombus,…

首先,生成vector<Rectangle>vector<Rhombus>并使用它们的子类属性。后来,我想组合所有四边形,即将两个向量组合成单个vector<quadrilateral>,因为我不再需要子类属性。将两个向量组合成一个的好处是,我可以将对vector<quadrilateral>的引用传递到程序的其他部分,在那里它与来自其他类的数据组合在一起。

所以我的问题如下:是否有可能通过只保留Rectangle的父变量来从Rectangle中获得Quadrilateral ?或者这是一个非常糟糕的想法,是否有更优雅的方法来实现它?

编辑:

在从答案中了解到这被称为切片后,我在什么是对象切片?中阅读了它。我决定采用Mohamad的建议,使用指针的向量,因为我认为这是一个优雅的解决方案,可能会给我最好的性能。

是的,你绝对可以通过"切片"对象的派生部分来做到这一点。

class Base {};
class Derived : public Base {};
Derived d;
Base b = d; // derived portion is sliced here

然而,在实践中,我从未见过有人故意选择切片他们的对象。我们经常被警告这是c++的一个'gotacha'。

为什么不用指针向量代替呢?

vector<Rectangle*>;
vector<Rhombus*>;
vector<quadrilateral*>;

这样就不会发生切片,如果这些类很大,您可能会从性能提升中获益,因为任何复制vector可能会对指针而不是整个对象进行复制。

是的,你可以这样做。您可以从子对象创建父对象,如下例所示:

struct Base { int base; };
struct Derived : Base { int derived; };
Derived der;
Base base = der;

这个过程被称为slicing,它在这里工作是因为基类将有默认的复制构造函数,接受对Base的const引用。由于派生类可以自动转换为对基类的const引用,所以一切都很顺利。但我对整体设计不太确定。通常要避免切片。

根据评论中的一些问题,我认为有必要澄清一下。

与它的外观相反,Base base = der;不调用赋值操作符。相反,它调用复制构造函数——这是变量声明的语义。它相当于Base base(der)。下面是一个更有趣的例子:

struct A {
   A(int ) { };
   A() = default;
   // A(const A& ) = delete;
};
A a = 5; // Are your eyes fooling you?

不要相信你的眼睛!从来没有调用过操作符=——在A定义中没有偶操作符=。相反,在语义上调用A(int)构造函数来创建临时的A,然后调用复制构造函数来创建A对象。然而,编译器通常会把对复制构造函数的调用优化掉,并且不会创建多余的临时副本。为了确保这种情况,取消标记为delete的复制构造函数的注释,程序将拒绝编译。