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

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 或为每个类生成唯一的整数。


1
听起来你真正需要的是在每个类上有一个静态整数来排序? - jk.
6个回答

22

如果您可以使用RTTI,

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

我认为你还需要

#include <typeinfo>

你必须在你的类中拥有一个虚函数以便vtable存在——析构函数也应该可以胜任。

更新:

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

  • 哈希typeid(*ptr).name()返回的字符串
  • 使用typeid(*a1).before(typeid(*a2))作为排序准则,虽然这样做在每次运行时没有任何确定性。

通常,在考虑RTTI时,最好看看是否可以通过编写良好的虚函数来更好地完成这些操作(例如双重分发)。不过,由于我不了解具体情况,因此无法说您的情况是否有更好的替代方案。


1
你需要记得同时包含 <typeinfo> - CB Bailey
2
@liaK,是的,基类必须至少有一个虚函数。 - avakar
@Tim 谢谢你的回复。我已经编辑了问题,以更好地反映我试图解决的问题。事实证明,简单的相等并不完全符合我的需求。 - bradgonesurfing
@bradgonesurfing,看看我的更新。我不确定是否理解正确。 - Tim Yates
1
"对返回自typeid(*ptr).name()的字符串进行哈希处理" - 哎呀!让我们看看:无论如何,OP都必须至少有一个虚函数才能使typeid工作。添加一个返回type_id作为简单“int”的虚函数不是最简单的方法吗?" - Maciej Hehl
显示剩余3条评论

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

注意解引用,这很重要。


2

你可以创建自己的类型标识符:

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

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

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

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

@Manoj:我不同意。typeTag是在子类构造函数中初始化的,因此它不能成为基类的私有成员。 - Adesit
我认为这是一个不好的想法,最好使用RTTI。 - piotr
@piotr,如果你不提供理由,就简单地说“这很糟糕”是不公平的。我不确定,但我认为我的想法有点像rtti内部的东西。一般来说,大多数时候坚持标准是好的,但有时最好自己实现一些东西。我们不知道发帖人的确切情况。例如,rtti在Android NDK下不受支持。 - Adesit
http://groups.google.com/group/android-ndk/browse_thread/thread/5804b3442bb394b1?pli=1 - piotr
有趣的链接:有人构建了一个定制版本的NDK,实际上支持RTTI。这很好。但请注意,那不是原始的谷歌NDK。 - Adesit
显示剩余2条评论

2

实际上,这个问题的答案相当简单。但需要更清晰地提出问题。

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

typeinfo支持==和name()方法。name()可以用于生成哈希值,==用于判断相等性。

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

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


1

C++ 中有一个名为 RTTI(运行时类型信息)的特性,它允许你做这样的事情。

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


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来自不同的共享库,则它仍然可以工作。

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