程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Howto:從C++對象指針得到類名

Howto:從C++對象指針得到類名

編輯:C++入門知識

JAVA程序在運行的時候,有豐富的動態類型信息。而C++則困難的多。C++的運行時類型信息有3種實現方式:語言本身的RTTI、MFC的CObject、QT的moc。下面僅介紹前兩種。
一、語言本身的RTTI:
如果是POD類型,如:
class PodPoint{
public:
    int x;
    int y;
};
那麼它和C語言中的struct沒有什麼區別。sizeof(PodPoint)=8。
偏移值 內容
0 x
4 y
 
別妄想能從它的對象指針中得到什麼類型信息。
 
如果它有虛函數,那麼就不一樣了
class PodPoint{
public:
    int x;
    int y;
    virtual ~PodPoint(){};
};
在32位程序中,sizeof(PodPoint)=12。這是因為凡是有虛函數,就必須有vtable。所以PodPoint的實際布局就變成了這樣:
偏移值 內容
0 指向vtable的指針
4 x
8 y
如果編譯的時候打開了RTTI(在vc2005及以上版本默認會打開),那麼就很有意思了。在vtable[-1]的位置,是一個特殊的指針,指向RTTI Complete Object Locator,它的第12個字節開始,是一個指針,指向type_info對象。於是我就寫了下面這樣的代碼:
void printMyClassInfo(void *p){
    type_info*** vtable=(type_info***)(*(int*)p);
    type_info** v1=vtable[-1];
    type_info* v=v1[3];
    printf("%s\n",v->name());
}
在有vtable的情況下,這個函數工作的非常好。
二、MFC的RTTI
MFC中的大多數對象都從CObject繼承而來,例如:
class MyPoint:public CObject{
public:
    int x;
    int y;
    DECLARE_DYNAMIC(MyPoint)
};
IMPLEMENT_DYNAMIC(MyPoint,CObject)
 
那麼我們就可以通過調用CObject的
virtual CRuntimeClass* GetRuntimeClass() const
來得到類名。這個函數一般就在vtable的第一個。
代碼如下:
void printClassInfo(void *p){
    int vtable=*(int*)p;
    CRuntimeClass* info;
    __asm{
        mov ecx,p;
        mov eax,vtable;
        call [eax];
        mov info,eax;
    }
    printf("%s",info->m_lpszClassName);
};
假如將上面的IMPLEMENT_DYNAMIC和DECLARE_DYNAMIC去掉,那麼輸出的結果將是”CObject”,而不是”MyPoint”,原因很簡單。因為子類沒有覆蓋基類的這個方法嘛。

 

作者 snnn

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved