在C ++中检查基类的两个实例是否属于同一个子类

时间:2010-10-05 12:25:24

标签: c++ dynamic-cast

以下代码解释了问题。填写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对实例进行分组。

FYI。我有一个迷你符号algerbra系统,所以要进行操作,有时候要知道类类型进行排序和重新排列表达式很重要。

所以给出了一个指针向量,用于实例如何通过type_id对它们进行分组。我要么需要能够散列type_id,要么为每个类生成一个唯一的整数。

6 个答案:

答案 0 :(得分:18)

如果您可以使用RTTI,

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

我认为你还需要

#include <typeinfo>

你必须在你的类中有一个虚函数才能存在vtable - 析构函数应该没问题。

<强>更新

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

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

通常在考虑RTTI时,最好使用精心设计的虚拟函数(例如double dispatch)来查看是否可以更好地完成任何操作。我真的不能说你的情况下是否有一个好的选择,因为我不明白具体细节。

答案 1 :(得分:7)

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

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

答案 2 :(得分:2)

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

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

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

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

C::C()
: typeTag(TypeTag::C_TYPE)
{
...
}

答案 3 :(得分:1)

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

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

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

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

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

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

根据您的编译器,可能使用或不使用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个实例,则第一次测试失败,但第二次测试失败。如果您的编译器缓存实例,第一个测试将成功(如果它是相同的类型)并且要快得多,因为它只是一个指针比较。如果您的编译器返回不同的实例,因为a1a2来自不同的共享库,它仍然可以工作。