运行时类型检查

Runtime type checking

本文关键字:检查 类型 运行时      更新时间:2023-10-16

我有一个关于运行时检查操作的问题。如果一个类包含从BPAbstract派生的vector对象(BPAbstract纯虚拟的),例如:

typedef std::shared_ptr<BPAbstract> Ptr;
std::vector<BPAbstract::Ptr> objects_;

现在假设我想在vector中对特定类型的对象进行分组。

template<class T>
void
GetObjectsByType( std::vector<typename T::Ptr> list ) const
{
    for( BPAbstract::Ptr i : objects_ )
    {
        // ???? ....
    }
}

什么是最好的实现?一种解决方案是尝试将i转换为类型 T,如果结果为非 null,那么我可以将其添加到列表中 list .我很确定有人知道更好的解决方案...

更好地实施这个想法的建议也是可以接受的!

你需要动态指针投射您的问题已经得到解答

template<class T>
void
GetObjectsByType( std::vector<typename T::Ptr> list ) const
{
    for( BPAbstract::Ptr i : objects_ )
    {
        T::Ptr candidate = std::dynamic_pointer_cast<T>(i);
        if (candidate)
            list.add(candidate);
    }
}
对不起

C++0X 语法,但动态强制转换是一种选择:

class Ai
{
public:
  virtual void a() = 0;
};
class Bi : public Ai
{
public:
  virtual void b() = 0;
};
class A : public Ai
{
public:
  virtual void a() override {printf("Aan");}
};
class B : public Bi
{
public:
  virtual void a() override {printf("Ban");}
  virtual void b() override {printf("Bbn");}
};

int _tmain(int argc, _TCHAR* argv[])
{
  typedef std::shared_ptr<Ai> Ptr;
  std::vector<Ptr> list;
  list.push_back(Ptr(new A()));
  list.push_back(Ptr(new B()));
  for (auto i = list.begin(); i != list.end(); ++i)
  {
    (*i)->a();
    auto b = std::dynamic_pointer_cast<Bi>(*i);
    if (b)
    {
      b->b();
    }
    //or, equally valid without additional shared_ptr overhead:
    auto bptr = dynamic_cast<Bi*>(i->get());
    if (bptr )
    {
      bptr->b();
    }
  }
}

但是,动态投射很慢。你真的想做一个静态强制转换(通过公开一个成员说嘿,我是 Bi(不推荐,因为它是一个巨大的痛苦,但维护)),或者使用多态性来选择行为(通过使 b() 成为 AI 中的函数,并让它在您希望它不执行任何操作的类中不执行任何操作)。