具有 dynamic_cast 和类型标识的 C++ 多态性
c++ polymorphism with dynamic_cast and typeid
假设我有一个父class Shape
和两个孩子班级class Square
和 class 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
?
编辑
查看其中一个答案,我应该指定Shape
、Square
和Circle
实际上是模板类。
我相信
您正在寻找的是一个简单的克隆功能,稍微扭曲的是它不会克隆数据,只会克隆类型。所以你可以添加这样的东西到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>;
那么一切都应该再次工作。没有其他代码更改。
当然,你应该使用智能指针而不是原始指针,但我想这是上面代码中的一个小修改。基本思想将保持不变。
相关文章:
- 调用具有未标识类型的类的方法
- 函数返回的 rvalue 引用(表达式)是 xvalue - 但没有标识?
- OOP 标识派生对象
- assert() 在发布模式下充当标识函数吗?
- AddressSanitizer 将 std::vector<T>::p ush_back 标识为释放后堆使用错误的原因
- 标识gdb调试器中符号的源文件名
- 如何跳过 CMake 编译器标识?
- 如何创建一个程序来标识最长的子字符串回文,而不考虑字母大小写
- 具有基于标识的相等性的有序关联容器
- 标识线程
- 一种类型特征,标识哪个类提供通过重载解析选择的函数
- C++ - 在运行时从基类指针标识派生类
- 标识使用的设计模式名称
- 使用 lambda 修改由打包参数标识的引用
- 使用 googletest 在类型参数化测试中标识使用的基类
- 如何获取由文件标识的流对象?
- 左值引用在传递标识函数后变得无效
- 共享指针交换方法标识更改
- 如何标识其功能当前正由可执行文件执行的共享库
- 在同一标头中定义但在类外部定义的模板构造函数未标识