具有 dynamic_cast 和类型标识的 C++ 多态性

c++ polymorphism with dynamic_cast and typeid

本文关键字:标识 C++ 多态性 类型 dynamic cast 具有      更新时间:2023-10-16

假设我有一个父class Shape和两个孩子班级class Squareclass Circle .

在我的代码中的某个时刻,我做了这样的事情:

Shape* genericshape;
if(a_time_consuming_test()){
    genericshape = new Square;
} else {
    genericshape = new Cricle;
}

后来我想创建另一个圆形或正方形,但我不想呼叫a_time_consuming_test()。那么我可以使用typeid或一些等效的东西直接创建"正确"的形状?像这样:

if(typeid(genericshape) == typeid(Square)){
    Square newsquare;
} else {
    Circle newcircle;
}

我想应该有这种解决方案,但这似乎没有高效,因为有一天我有第三种形状,就像Triangle一样,我会需要检查Shape的每个孩子。会是这样吗可能?

Shape* newshape(&genericshape);

我的意思是,newshape是同一个子类上的指针吗 genericshape

编辑

查看其中一个答案,我应该指定ShapeSquareCircle实际上是模板类。

我相信

您正在寻找的是一个简单的克隆功能,稍微扭曲的是它不会克隆数据,只会克隆类型。所以你可以添加这样的东西到Shape

struct Shape
{
  virtual std::unique_ptr<Shape> createEmptyObject() const = 0;
  // The rest as before
}:

struct Circle
{
  std::unique_ptr<Shape> createEmptyObject() const override
  { return std::make_unique<Circle>(/*ctor args here*/); }
  // The rest as before
};

然后像这样使用它:

Shape* genericshape;
if(a_time_consuming_test()){
    genericshape = new Square;
} else {
    genericshape = new Cricle;
}
// ...
auto anotherShape = genericshape->createEmptyObject();

注意:如果您无法访问 C++14,则必须将make_unique替换为手动构建的unique_ptr

return std::unique_ptr<Shape>(new Circle(/*ctor args here*/));

如果您已准备好编辑以下类型列表,则每次添加新形状时

using shapes = typelist<circle, rectangle>;

那么我认为以下解决方案应该有效(逐步解释):

shape* create(shape const * s)
{
    return create_impl(shapes(), s);
}

其中create_impl和其他支撑定义为:

template<typename T, typename ... Ts>
struct typelist{};
using shapes = typelist<circle, rectangle>;
template<typename T, typename ...Rest>
shape* create_impl(typelist<T, Rest...>, shape const *s)
{
     if ( typeid(T) == typeid(*s) )
        return new T();
     else
        return create_impl(typelist<Rest...>(), s);
}
template<typename T>
shape* create_impl(typelist<T>, shape const *s)
{ 
     return typeid(T) == typeid(*s)? new T() : nullptr;
}

稍后,如果您添加一个新形状,例如triangle,则只需将其添加到类型列表中:

using shapes = typelist<circle, rectangle, triangle>;

那么一切都应该再次工作。没有其他代码更改。

当然,你应该使用智能指针而不是原始指针,但我想这是上面代码中的一个小修改。基本思想将保持不变。