如何使用type_info判断一个类型是否是子类?

4

我使用带有RTTI的C++。我有一个类的type_info。如果我只有type_info,我如何判断另一个类是否是第一个类的子类?

#include <typeinfo>

class Foo             { public: virtual ~Foo() {} };
class Boo: public Foo { public: virtual ~Boo() {} };
class Bar             { public: virtual ~Bar() {} };

template<class T>
bool instanceOf(const type_info& info) {
  // ANSWER COMES HERE!!
}

int main(int argc, const char* argv[]) {
  const type_info& fooInfo = typeid(Foo);
  const type_info& barInfo = typeid(Bar);

  bool booIsFoo = instanceOf<Boo>(fooInfo); // should be true
  bool booIsBar = instanceOf<Boo>(barInfo); // should be false

  return 0;
}

我想存储type_info,并稍后测试继承关系。std::is_base_ofdynamic_cast需要类型作为模板参数,但我无法将其存储以供以后使用。 - aedm
@ThomasMoulard:不幸的是,我要测试的类型列表是由用户操作在运行时决定的。我可以将所有对象都与所有类型进行测试,但这似乎有些过度。 - aedm
这听起来像是在询问关于你所认为的解决方案Y的问题,而这个问题X却没有透露出来。最好是直接问X的问题,因为解决方案Y并不好。 - Cheers and hth. - Alf
那么,你的最终目标不是解决实际问题,而是学习某些特定语言功能的技巧?如果你(A)有一个实际问题,并且(B)展示了你尝试过的内容,然后(C)指出了它失败的地方,那么Stack Overflow是最有效的。这看起来非常像你有一个实际问题,想出了一个解决方案,但它没有起作用,因为你无法解决这个子问题。然后你发布了这个子问题,询问如何解决它。很可能你的整体问题有一个简单的解决方案,但你狭窄的子问题与整体问题无关。这是X/Y。 - Yakk - Adam Nevraumont
1
这个答案可能会有所帮助:https://dev59.com/02PVa4cB1Zd3GeqP7Jmj#10508092 - Кое Кто
显示剩余5条评论
1个回答

5

如果您只有两个typeinfo A和B,则无法确定A是否是B的子类。

您可以:

  1. 自己存储此信息(在运行时填充的静态结构?)
  2. 使用类型名称进行有根据的猜测(即解析类型信息字符串并相应地命名类型)。

之前的答案。它们要求您以某种方式实例化类型:

type_info不是这个问题的正确工具,如果您绝对想在运行时检查,请使用dynamic_cast

template<class Base, typename Derived>
bool instanceOf(const Derived& object) {
  return !dynamic_cast<Base*>(object);
}

您也可以在编译时使用Steephen提到的std::is_base_of进行检查(需要C++11版本)。
template <typename Base, typename Derived>
static constexpr bool instanceOf() {
    return std::is_base_of<Base, Derived>()
}

另一个解决方案:
template <typename Base, typename Derived>
bool instanceOf(const Derived& object) {
  try {
      throw object;
  } catch (const Base&) {
      return true;
  } catch (...) {
      return false;
  }
}

1
return ! (dynamic_cast<T*>(object)) - Ryan
谢谢,但这些解决方案要求我将超类指定为模板参数,以便在编译时可用。然而,我想针对我确定(并存储)的类型测试继承关系。这就是为什么我需要type_info的原因。 - aedm
2
一个类型信息仅仅是一个字符串,它并不持有任何关于关系的信息,因此您需要依靠其他额外的机制。 (编辑:修正注释) - Thomas Moulard
谢谢,这解释了为什么这样做不太可能。:( 我有点希望它包含的信息不仅仅是一个简单的字符串。 - aedm
我已相应地更新了答案。虽然直接实现不可能,但如果您手动存储类型之间的关系,您应该能够以某种方式实现您想要的内容... - Thomas Moulard
我不明白 dynamic_cast 的例子应该如何工作。 Derived 很可能无法转换为 Base*。 可能应该这样写:return !dynamic_cast(&object); - The19thFighter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接