• 全部
  • 问答

RTTI问题:typeid()是如何实现的?

eric8231 2003-05-23 03:02:45
使用虚函数可以实现运行时的多态性;

但假如在某些不能使用虚函数的情况下(比如不能直接修改基类的代码时),这时利用dynamic_cast()是个不错的主意;

但,在必须知道某个“确切”类型时,只好直接与RTTI打交道了。
利用 typeid()以及一个多态对象,便可以知道这个多态对象的确切类型,
例如像这样:

#include <iostream>
#include <cstdlib>
using namespace std;

class A {
public:
void iam() { cout<<typeid(*this).name()<<'\n'; system("pause");}

private:
virtual void do_nothing() {}
};

class B: public A {};

int main()
{
B b;

A* pa=&b;

pa->iam();

return 0;
}

我的问题是:
如何通过typeid()得到多态对象的确切类型?或者说,
typeid(多态对象).name() 具体是如何实现的?(需要编译器做点什么吗?)

THANKS :p
...全文
139 点赞 收藏 17
写回复
17 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
Cypher 2003-05-28
To stukov2002(卡拉是头猪) :

MFC好象是用自己的方式实现的,和C++标准中的RTTI有所区别,因为M$最初设计MFC时标准中有关RTTI的部分还不完善。
回复
深入浅出mfc中有过关于rtti的讨论.
回复
ckacka 2003-05-27
Cypher(Nothing):
好的,谢谢!
回复
devajasy 2003-05-26
建议你看 inside the c++ object model
回复
Cypher 2003-05-26
To ckacka(小红帽) :

我在公司不能上网,而且我写的东西太乱了,也不全,最近工作太忙了没再空儿再深入下去了。等我有点儿时间整理一下想办法把它带出来吧。
回复
ckacka 2003-05-25
Cypher(Nothing):
我很有兴趣看看,谢谢
回复
Cypher 2003-05-25
具体的编译器有不同的实现。前一段时间我曾分析过VC及Tornado(一个实时系统的编译器,大家可能不熟悉。从GCC演化来的,但有所区别),当时做了一些记录,不过没带出来,记得不是很准确了。

VC中是调用了一个函数___RTtypeid,没源码,我跟踪过,但记不太清楚了。

VC下对象的前32位(指针)是vptr,而vtable中第一个长字是虚函数指针,类似于:
struct vtable_node
{
void *pFunc;
};

struct vtable_node vtable[xxx]; // 数组,越函数的下标从0开始。

其中vtable[-1]是和RTTI有关的。


Tornado的编译器(不知普通的GCC是不是也这样处理)越函数表项是8字节的,其实两个字节的this指针调用量(用于处理多继承),四个字节虚函数地址,另外两个字节我没找到作用。和VC不同的是它的虚函数是从vtable的下标为1也就是第二项开始的,第一项是RTTI相关的,好象是那个项中虚函数地址的地方用来调用找到其对应的type_info对象。


如果谁有兴趣我看能不能找时间把我原来记录的东西整理一下带出来,比较乱。
回复
justaseeker 2003-05-24
这是在编译时候在符号表中添加的控制信息确定的
回复
zjw2723114 2003-05-24
==========
实现构想:
==========

建一份“类别型录”的链表 以 CRuntimeClass 描述之
struct CRuntimeClass
{
LPCSTR m_lpszClassName; //类名

CRuntimeClass* m_pBaseClass; //指向基类
static CRuntimeClass *pFirstClass //指向链表头
CRuntimeClass* m_pNextClass //指向下一个结点
};

===================================
每个类都拥有一个CRuntimeClass 成员变量,类构造的时候,先初始化CRuntimeClass
这样通过特定的“宏”就形成了一张“类型识别网”,查找具体属于哪种类型就“有据可依”





回复
hpho 2003-05-23
这个问题在<Inside The C++ Object Model>最后那章有解答。

[p317]
"RTTI只适用于多态类(Polymorphic classes), 事实上type_info object也适用于内建类型, 以及非多态的使用者自定类型. 这对于handling的支持有必要. ..."

"typeid(double)...;
会传回一个const type_info&. 这与先前使用多态类型的差异在于, 这时候的type_info object 是静态取得, 而非执行期取得. 一般的实现策略是在需要是才产生type_info object ,
....."
摘《深度探索 C++对象模型》


回复
luohualiushui 2003-05-23
如果没有vtable,编译器当然可以放在其他地方
我要说的是vtable里面有放typeinfo的地方
回复
loveghb 2003-05-23
楼上说什么?
我没听懂。
没有虚函数当然不需要vtabl了。
回复
worry 2003-05-23
如果没有虚函数呢?vtable就不应该存在了,那type info放哪里呢,呵呵。
回复
luohualiushui 2003-05-23
在Vtable里面有专门放type information的地方

typeid()应该就是用到那里面的信息了
回复
eric8231 2003-05-23
谢谢:> 正如你所说的“如果你使用了多态,但是还要区分类的具体类型,那么多半是你的设计有问题”,我举的那个例子其实也反映了这种矛盾。

再说说typeid()的实现方法,在vtbl里加个指针? 指向一个type_info,然后在type_info里用(比如)字符串保存具体类型的名字?
回复
liu_feng_fly 2003-05-23
哦,再说一句,如果你使用了多态,但是还要区分类的具体类型,那么多半是你的设计有问题,应该考虑重新设计。
回复
liu_feng_fly 2003-05-23
一般是在vatble里面加上一点东西来标识一下。
回复
发帖
C++ 语言
创建于2007-09-28

5.9w+

社区成员

C++ 语言相关问题讨论,技术干货分享,前沿动态等
申请成为版主
帖子事件
创建了帖子
2003-05-23 03:02
社区公告
暂无公告