12

下面的代码解释了这个问题。填写 same_sub_class 以检测两个指向虚拟基类 A 的指针是否实际上是同一个具体类。

struct A {
    ...
}:

struct B : public A {
    ...
}:

struct C : public A {
    ...
}


bool same_sub_class(A * a1, A * a2){
    // Fill this in to return true if a1 and a2 are
    // of the same concrete class
}

编辑:

当我查看我的应用程序时,我需要一些与上面略有不同的东西。我需要能够按它们的 type_id 对实例进行分组。

供参考。我有一个迷你符号代数系统,所以要进行操作,有时了解类类型对于排序和重新排列表达式很重要。

因此,给定一个指向实例的指针向量,如何按它们的 type_id 对它们进行分组。我要么需要能够散列 type_id 要么为每个类生成一个唯一的整数。

4

6 回答 6

22

如果你可以使用 RTTI,

typeid(*a1) == typeid(*a2)

我想你也需要

#include <typeinfo>

而且你的类中必须有一个虚函数,这样 vtable 才能存在——析构函数应该可以。

更新

我不确定我是否完全理解您对分组的要求(您需要某种确定性排序吗?子类应该发生什么?),但您可以尝试使用从运算符返回的typeid

  • 散列从返回的字符串typeid(*ptr).name()
  • 用作typeid(*a1).before(typeid(*a2))排序标准。但是,这在运行之间没有任何确定性。

一般来说,在考虑 RTTI 时,最好看看是否可以使用精心设计的虚拟函数(例如double dispatch)更好地完成其中的任何一项。不过,我真的不能说你的情况是否有一个好的选择,因为我不了解具体情况。

于 2010-10-05T12:30:13.257 回答
9
typeid(*a1) == typeid(*a2)

请注意取消引用,这很重要。

于 2010-10-05T12:32:40.580 回答
2

您可以制作自己的类型标识符:

struct A{
...
protected:
 enum TypeTag{B_TYPE, C_TYPE};
 TypeTag typeTag;
};

然后在子类的构造函数中:

B::B()
: typeTag(TypeTag::B_TYPE)
{
...
}

C::C()
: typeTag(TypeTag::C_TYPE)
{
...
}
于 2010-10-05T12:44:31.317 回答
2

实际上,对此有一个相当简单的答案。但这涉及更清楚地提出问题。

(A) 如果我想将 typeinfo 对象存储在 unordered_set 中,我需要做什么?

typeinfo 支持 == 和 name() 方法。该名称可用于生成哈希和 == 用于相等

(B) 如果我想将 typeinfo 对象存储在 ordered_set ( std::set ) 中,我需要做什么?

typeinfo 支持 == 和 before() 方法。通过对这两种方法进行一些包装,我可以为比较函数实现一个接口,该接口给我严格的弱排序。

于 2010-10-07T08:43:23.667 回答
1

C++ 中有一个称为 RTTI(运行时类型信息)的功能,它允许您执行此类操作。

进行运行时类型检查的另一种可能性是创建一个基类,所有类都从该基类派生。在您的基类中包含一个字段,该字段包含其类型为字符串或数字。

于 2010-10-05T14:24:15.790 回答
0

根据您的编译器,一个可能适用于 RTTI 也可能不适用于 RTTI 的技巧如下

const type_info &a1_type_info= typeid(*a1);
const type_info &a2_type_info= typeid(*a2);

return &a1_type_info==&a2_type_info || a1_type_info==a2_type_info;

如果您的编译器type_info按值创建实例,这将在第一次测试失败但在第二次测试成功。如果您的编译器缓存了实例,那么第一个测试将成功(如果它是相同的类型)并且更快,因为它只是一个指针比较。如果您的编译器因为来自不同的共享库a1而返回不同的实例,它应该仍然可以工作。a2

于 2010-10-05T16:30:06.067 回答