假设我有一个父class Shape
和两个孩子班class Square
和
class 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
?
查看其中一个答案,我应该指定Shape
,Square
和Circle
实际上是模板类。
答案 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>;
然后一切都应该再次运作。没有其他代码更改。
当然,您应该使用智能指针而不是原始指针,但我想这是上述代码中的一个小修改。基本想法将保持不变。