【问题标题】:What is the simplest RTTI implementation for C++?C++ 最简单的 RTTI 实现是什么?
【发布时间】:2009-07-03 21:48:05
【问题描述】:

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

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

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

-- 编辑--

我没有在编译器上工作,它是一个 ia32-g++。

【问题讨论】:

  • 您是否正在编写/修改编译器或语言运行时,或者您打算将其放入何处?多一点上下文会很好。
  • 如果你的内存有限,你不应该启用RTTI,甚至尝试使用异常。最好考虑另一种方法。
  • 如果抛出异常,throw nust 以某种方式对异常类型信息进行了编码,所以我不明白为什么需要一些“替代”方法。正如 jalf 所说,请向我们提供有关您实际尝试做的更多信息。

标签: c++ exception-handling rtti


【解决方案1】:

当您在嵌入式环境中工作时,您可能喜欢极少的解决方案,并且您可以利用有关您的编译器的非标准或不可移植的事实。

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

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

如果是这样,您可能可以像这样访问 vtable:

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

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

所以一个“类型开关”(这就是 catch 基本上是)会做这样的事情:

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 重用于派生类。这意味着为了区分两种异常类型,它们必须各自覆盖一个虚函数,以确保它们有自己的虚表。

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

【讨论】:

  • 你能展示一种在第一个代码中获取“ptr”的方法吗?而且我也不理解“obj”这个角色。
  • 抱歉,打错了。它只是一个指向多态类型对象的指针。
【解决方案2】:

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

【讨论】:

  • 当然,要存在虚函数,您可能会使用某种虚函数指针表。以某种方式可以用于 rtti...
  • 虽然比巨型枚举方法更复杂 ;)
  • 还应该添加一个少一点的跨平台...找到那些 VTable 可能是一项非常艰巨的工作。
  • 我的意思是:如何在不使用某种 vfptrtable 的情况下执行抽象虚函数 GetType()?你说,你用虚函数实现 RTTI,但对于虚函数,你已经需要某种 RTTI。
  • 嗯,我觉得有点遥不可及。系统中的对象太多。但对于较小的“静态”开发,它是一个不错的选择。
猜你喜欢
  • 2011-02-16
  • 2011-03-21
  • 2018-02-09
  • 1970-01-01
  • 2010-11-09
  • 2010-11-23
  • 1970-01-01
  • 2017-05-21
相关资源
最近更新 更多