[英]Lookup a specific type from a list in C++ using templates not including base classes
这可能是不可能的,因此该问题的替代解决方案也将足够
我有要跟踪的活动列表
class Activity {
public:
virtual void DoSomething() = 0 ;
};
std::vector<Activity*> activities;
假设我有以下子课程
class GraphicsActivity : public Activity {
public:
virtual void DoSomething() { }
void HandleGraphics() { /* do some management */; }
};
class UpdateActivity : public Activity {
public:
virtual void DoSomething() { ; }
};
class PhysicsActivity : public Activity {
public:
virtual void DoSomething() { ; }
};
现在,我们要从列表中获取这些活动之一。 一个函数看起来像
template<typename T> T* GetActivity() {
for(int i = 0; i < activities.size(); i++) {
T* cast = dynamic_cast<T*>(activities[i]);
if(cast != nullptr) {
return cast;
}
}
return nullptr;
}
我们可以这样使用它:
activities.push_back(new GraphicsActivity());
activities.push_back(new PhysicsActivity ());
activities.push_back(new UpdateActivity ());
GraphicsActivity* g = GetActivity<GraphicsActivity>();
假设我们还有另一个活动,该活动需要使用多态性来使用某些基类的方法。
class 3DGraphicsActivity : public GraphicsActivity {
public:
void Handle3DGraphics() {
/* Utilize base class function */
this->HandleGraphics();
/* do some extra work */
}
};
现在,我们希望获得与以前相同的活动,并且列表现在看起来像下面的确切顺序:
activities.push_back(new GraphicsActivity3D());
activities.push_back(new GraphicsActivity());
activities.push_back(new PhysicsActivity ());
activities.push_back(new UpdateActivity ());
但是,我们需要GraphicsActivity
的原始类型,因此我们去获取它:
GraphicsActivity* g = GetActivity<GraphicsActivity>();
实际上,我们将获得一个指向列表中第一个条目的指针,因为它共享了GraphicsActivity
类型的基类。
这就是问题所在:如何编写这样的列表,其项必须共享相同的基类Activity
同时还能够从列表中获取确切的类型,而不会陷入我们刚刚解释的dynamic_cast
陷阱中?
typeid
运算符可用于检查多态对象是否具有某些确切的最派生类型。
#include <typeinfo>
// ...
template<typename T> T* GetActivity() {
for(int i = 0; i < activities.size(); i++) {
auto* act = activities[i];
if (act != nullptr && typeid(*act) == typeid(T)) {
return dynamic_cast<T*>(act);
}
}
return nullptr;
}
请谨慎使用此模式,因为它会限制创建一个类的能力,该类的行为与其他类完全相同,除了特定的更改。 但这可能适合您的界面。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.