C++ 如何返回未知的派生类
C++ How can I return an unknown derived class?
我有一个基类Shape
,它有像Ellipse
和Rectangle
这样的派生类。
在一个函数中,我有一个变量:
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
返回具有切片对象的效果,因此调用方仅接收Rectangle
Shape
部分的副本,而不是其余部分的副本。
假设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
持有的对象将被销毁,任何使用它的尝试都会给出未定义的行为。
类型是在编译时确定的,因此不能根据运行时信息(如 button
的值(更改变量的类型。
相反,您需要使用类似 dynamic_cast<Rectangle&>(active_shape)
的东西进行测试以查看它是否是一个矩形,然后在该测试通过时使用它(如果形状不是矩形,它将引发异常(
编辑:不过,您必须更改函数才能不按值返回形状。 我建议返回 std::unique_ptr 返回语句如下所示:
return std::make_unique<Ellipse>(active.getFillColor(), active.getBorderColor(), active.getP1(), active.getP2(),false);
在代码的下面行中,对象切片将发生,因此您的代码无论如何都是有问题的。
activeShape = updateShape(isButton, activeShape, true);
在这里,如果 updateShape 返回除 shape 以外的任何类型,那么您的对象将在返回之前被切片为形状类型。因此,activeShape可能包含错误的切片对象。
要改进它,您应该返回指向基类(形状(的指针并使用它。
- 为什么使用 "this" 指针调用派生成员函数?
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 继承期间显示未知行为的子类
- 在派生函数中指定void*参数
- 如何通过派生类函数更改基类中的向量
- 如何委托派生类使用其父构造函数?
- 输入中的字符串数未知(以字母表示)
- 如何使用单独文件中的派生类访问友元函数对象
- dynamic_cast到具有未知模板参数的派生类型
- 如何创建指向派生类的新指针,该派生类在C++编译时未知
- 将unique_ptr的内容复制到未知派生类
- 将基类指针转换为未知派生类指针
- C++派生类的设置属性到从同一基类派生的未知类对象
- 类成员是类型未知的派生对象
- 从基类到未知派生类的强制转换
- 通过抽象基类调用未知派生类的复制构造函数
- C++ 如何返回未知的派生类
- 从未知的派生类调用接口函数(多重继承)
- 派生类中的类型定义未知
- 在c++中创建未知派生类的实例