繁体   English   中英

使用不包含基类的模板从C ++列表中查找特定类型

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM