什么是C ++最简单的RTTI实现?

时间:2009-07-03 21:48:06

标签: c++ exception-handling rtti

我正在尝试为嵌入式操作系统实现异常处理,并且我一直在研究如何检测抛出的“异常”的类型(以选择适当的处理程序)。

异常处理的保存和恢复上下文部分已经完成,但由于无法检测抛出的“异常”的类型,因此无法使用特定的句柄。 c ++的标准RTTI实现过于依赖其他库,因此我目前认为它不可用。

考虑到我的目标是嵌入式系统,因此我无法创建太多代码,我可以获得(或制作)的“运行时类型信息”的最小实现是什么?

- 编辑 -

我不是在编译器,它是一个ia32-g ++。

2 个答案:

答案 0 :(得分:11)

当您在嵌入式环境中工作时,您可能会支持极少的解决方案,并且您可以利用有关编译器的非标准或非便携性事实。

如果一个类在C ++中是多态的(至少有一个自己的虚函数),它可能有一个指向嵌入其中某个地方的vtable的指针。可能是vtable指针出现在内存中对象布局的开头。

许多使用C ++ ABI的编译器都是如此 - a related SO question here

如果是这样,你可能能够像这样进入vtable:

void *get_vtable(void *obj)
{
    return *(reinterpret_cast<void **>(obj));
}

然后你可以比较两个指向对象的vtable,看它们是否指向同一类型的对象。

所以“类型切换”(基本上就是捕获)会做这样的事情:

P p;
Q q;
if (get_vtable(caught) == get_vtable(&p))
{
    // it's a P...
}
else if (get_vtable(caught) == get_vtable(&q))
{
    // it's a Q...
}

您可以在CATCH宏中隐藏该模式。

重点 - 如果从基类派生类,但派生类不覆盖任何虚函数或添加任何新的虚函数,那么编译器可以想象重用基类的vtable for派生类。这意味着为了区分两种异常类型,它们必须各自覆盖一个虚函数,以确保它们有自己的vtable。

请注意,这只是异常处理所涉及的一小部分。还有解决堆栈的小问题!跳转到处理程序时,需要调用堆栈上所有对象的析构函数。这不仅仅是做setjmp / longjmp的问题。

答案 1 :(得分:2)

我能想到的最简单的RTTI是从具有纯虚拟“GetType()”函数的公共库中派生所有类。要么让它返回一个字符串,要么创建一个包含所有类型的巨大枚举。它非常简单,速度快,内存开销低。然而,并不是特别灵活。