c ++多态与dynamic_cast和typeid

时间:2015-04-20 15:13:57

标签: c++ casting polymorphism

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

在我的代码的某些时候,我做了类似的事情:

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

后来我想创建另一个Circle或Square,但我不想 致电a_time_consuming_test()。我可以使用typeid或某些等价物 直接创造"权利"形状?类似的东西:

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

我想应该有这样的解决方案,但这似乎并非如此 因为我有第三个形状的那天,比如Triangle,我会这么高效 需要检查Shape的每个孩子。会是这样的 可能?

Shape* newshape(&genericshape);

我的意思是,newshape会成为同一子类的指针 genericshape

修改

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

2 个答案:

答案 0 :(得分:3)

我相信你正在寻找的是一个简单的克隆功能,稍微扭曲它不会克隆数据,只有类型。因此,您可以将此类内容添加到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*/));

答案 1 :(得分:0)

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

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>;
然后一切都应该再次运作。没有其他代码更改。

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