dynamic_cast 和 typeid 的 c++ 多态性

c++ polymorphism with dynamic_cast and typeid

假设我有一个 parent class Shape 和两个 children class class Squareclass Circle.

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

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

后来我想创建另一个圆形或方形,但我不想 打电话 a_time_consuming_test()。那么我可以使用 typeid 或类似的东西吗 直接创建 "right" 形状?像 :

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

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

Shape* newshape(&genericshape);

我的意思是,newshape 会是与 child class 相同的指针吗 genericshape?

编辑

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

我相信您正在寻找的是一个简单的克隆功能,它不会克隆数据,只会克隆类型。所以你可以将这样的东西添加到 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>;

那么一切都应该会恢复正常。没有其他代码更改。

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