C++ 如何返回未知的派生类?

标签 c++ inheritance polymorphism

我有一个基类 Shape,它具有 EllipseRectangle 等派生类。

在一个函数中,我有一个变量:

Shape activeShape(black, black, {0,0}, {0,0}, false);

然后在该函数中:

activeShape = updateShape(isButton, activeShape, true);

updateShape 看起来像这样:

Shape updateShape(int button, Shape active, bool leftClick)
{
    switch(button)
    {
        case 1:
            return active;
        case 2:
            return Line(active.getFillColor(), active.getBorderColor(), active.getP1(), active.getP2(),false);
            break;
        case 3:
            return Rectangle(active.getFillColor(), active.getBorderColor(), active.getP1(), active.getP2(),false);
            break;
        case 4:
            return FilledRectangle(active.getFillColor(), active.getBorderColor(), active.getP1(), active.getP2(),false);
            break;
        case 5:
            return Ellipse(active.getFillColor(), active.getBorderColor(), active.getP1(), active.getP2(),false);
            break;
        case 6:
            return FilledEllipse(active.getFillColor(), active.getBorderColor(), active.getP1(), active.getP2(),false);
            break;
        default:
            if(leftClick)
            {
                active.setColor(getEnumColor(button), active.getBorderColor());
            }
            else
                active.setColor(active.getFillColor(), getEnumColor(button));
            break;
    };
    return active;
}

所以当我返回诸如 Rectangle 之类的东西时,它们被转换为 Shape。这完全不是我想要的。

我需要做什么才能使 activeShape 成为 Shape 的派生类之一?

最佳答案

一旦创建了一个对象,就不可能改变它的类型(例如,基于运行时获得的按钮信息)。返回 Rectangle作为Shape具有切片对象的效果,因此调用者仅收到 Shape 的拷贝Rectangle 的一部分,但不是其余部分。

假设Shape是一个多态基类(即它提供可以由派生类专门化的虚函数),一个 Shape * (指向形状的指针)可以指向 Rectangle .然而,有必要正确管理对象的生命周期。

您可以使用智能指针来处理所有这些问题,例如在 C++11 及更高版本中,std::unique_pointer<Shape> .

std::unique_pointer<Shape> updateShape(int button,
        std::unique_pointer<Shape> active, bool leftClick)
{
    switch(button)
    {
        case 1:
             break;    // don't change active
        case 2:
            active = new Line(active->getFillColor(), active->getBorderColor(), active->getP1(), active->getP2(),false);
            break;
        case 3:
            active = new Rectangle(active->getFillColor(), active->getBorderColor(), active->getP1(), active->getP2(),false);
            break;
        case 4:
            active = new FilledRectangle(active->getFillColor(), active->getBorderColor(), active->getP1(), active->getP2(),false);
            break;
        case 5:
            active = new Ellipse(active->getFillColor(), active->getBorderColor(), active->getP1(), active->getP2(),false);
            break;
        case 6:
            active = new FilledEllipse(active->getFillColor(), active->getBorderColor(), active->getP1(), active->getP2(),false);
            break;
        default:
            if(leftClick)
            {
                active->setColor(getEnumColor(button), active->getBorderColor());
            }
            else
            {
                active->setColor(active->getFillColor(), getEnumColor(button));
            }
            break;
     }
     return active;
}

这样做的原因是 std::unique_pointer管理动态分配(使用运算符 new 创建)对象的生命周期。它通过存储指向对象的指针并分配给 std::unique_pointer<Shape> 来实现。更改指针(使其指向不同的对象)。重要的是,分配给智能指针也会释放它之前管理的对象。

请注意,由于 std::unique_pointer将使用运算符 delete在其生命周期结束时销毁包含的对象,Shape必须有一个虚拟析构函数。如果不这样做,将导致使用运算符 delete 时出现未定义的行为。 .

这个的用法是这样的

 std::unique_pointer<Shape> activeShape(new Rectangle( whatever_parameters));

 activeShape = updateShape(button, activeShape, leftClick);

请记住 activeShape是一个智能指针。所以使用包含的Shape对象需要指针语法 ( activeShape->whatever ) 而不是成员语法 ( activeShape.whatever )。

因为 active参数被(按值)传递给函数并返回,分配返回值是必要的。如果,而不是

activeShape = updateShape(button, activeShape, leftClick);

你只是

updateShape(button, activeShape, leftClick);   // returned object is discarded

(即不要将返回值赋给任何东西),最终效果是 activeShape 持有的对象将被销毁,任何使用它的尝试都会产生未定义的行为。

关于C++ 如何返回未知的派生类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39824833/

相关文章:

c++ - 程序已退出,代码为 -2147483645

c# - 继承:根据具体对象在运行时调用正确的方法

c++ - 如何正确使用 "C++ Core Guidelines: C.146: Use dynamic_cast where class hierarchy navigation is unavoidable"

c - C 中的多态性和赋值运算符

c++ - C++ 中的命名空间和运算符重载

c++ - 获取内部对象内部的外部对象指针

c++ - 将 C++ 与 Objective-C 结合使用,如何修复 "Conflicting declaration ' typedef int BOOL'"?

java - 如何提示接口(interface)的植入有一些指定的数据成员?

c++ - 无递归初始化

java - 多态类/多态性/内部类-获取错误信息