[ 永遠的UNIX::UNIX技術資料的寶庫 ]   GB | BIG5

首頁 > 編程技術 > C/C++ > 正文
C++對象的放置
本文出自:http://www.asfocus.com 作者: hucong (2002-02-04 07:15:00)
(聲明:本文參考了《深度探索c++對象模型》這本書,我連例子都和此書一樣,
如有人認為是偷的話,還請各位原諒,^_^) 
經歷過從c到c++的人,一定想知道c++編譯器是如何安排類的成員的.這裡我 
大概的作一下介紹,並有一些代碼供你進行測試,希望對大家有點作用吧. 
其實這裡的標題或許有點大了,簡單的說,類的非static成員是按照聲明的順序 
存放在內存區的,而類的static成員和一般的static變量的存儲格式一樣.我不從 
簡單的東西入手了,直接從一個相對復雜的多重繼承的例子入手.看下面的代碼: 
class Point2d 

public: 
int _x,_y; 
virtual f(){}//保証Point2d有個虛擬指針 
}; 
class Point3d:public Point2d 

public: 
int _z; 
}; 
class Vertex 

public: 
virtual void h(){}//保証Vertex3d的第二基礎類有個vptr 
int next; 
}; 
class Vertex3d:public Point3d,public Vertex 

public: 
int mumble; 
}; 
Point2d,Point3d,Vertex,Vertex3d的繼承關系能看得出來吧.再看主函數 
int main() 

Vertex3d v3d; 
Vertex*pv; 
pv=&v3d; 
int*x=&v3d._x;//獲取v3d的成員的地址 
int*y=&v3d._y; 
int*z=&v3d._z; 
int*n=&v3d.next; 
int*mem=&v3d.mumble; 
cout<<"*v3d= "<<&v3d<<endl;//輸出第一個vptr 
cout<<"*x= "<<x<<endl;//輸出成員的x的地址 
cout<<"*y= "<<y<<endl;//…. 
cout<<"*z= "<<z<<endl;//….. 
cout<<"*pv= "<<pv<<endl;/.輸出第二個vptr 
cout<<"*n= "<<n<<endl;//……. 
cout<<"*mem= "<<mem<<endl;//…….. 
return 0; 

我在vc6.0編譯運行的結果是: 
&v3d = 0x0012ff64 
x = 0x0012ff68 
y = 0x0012ff6c 
z = 0x0012ff70 
pv = 0x0012ff74 
n = 0x0012ff78 
mem = 0x0012ff7c 
從上面的輸出結果來看,對象是如何布局的就一幕了然了,如果你不信,可以自己可 
以試試看,輸出Vertex3d的尺寸瞧一瞧,^_^.注意,Vertex3d內有兩個vptr,如果還 
不知道為什會有的話,建議你先去看看書吧!! 

補充:我想到另一個比較直觀的方法,就是利用Placement Operator New(PON)的 
方法,相對應的還有Placement Operator Delete.至這些概念,我就不多說了,^_^. 
剛才看到那些地址都是內存中的,但可以利用(PON)把那些地址放倒一個數組中 
去,那樣會更直觀,不信,你看著: 
#include<iostream.h> 
#include<new.h> 
class Point2d 

public: 
int _x,_y;// 
Point2d(){ 
_x=10; 
_y=20; 

virtual f(){} 
}; 
class Point3d:public Point2d 

public: 
int _z; 
Point3d(){_z=30;} 
}; 
class Vertex 

public: 
int next; 
Vertex(){next=40;} 
virtual void f(){} 
virtual void g(){} 
virtual void h(){} 
}; 
class Vertex3d:public Point3d,public Vertex 

public: 
int mumble; 
Vertex3d(){mumble=50;} 
}; 
int main() 

long str[30]; 
Vertex3d*array=new(str)Vertex3d; 
for(int i=0;i<sizeof(Vertex3d)/4;i++) 

cout<<str[i]<<endl; 

//這裡需要顯示調用Vertex3d的析構函數, 
return 0; 


讓我慢慢說來,這裡的一些類,只是添加了構造函數而已,為的是能夠直觀.我定義 
了一個數組為的放置Vertex3d對象,類型為long是由上面的類的每個成員都是四 
個字節,而虛擬指針(vptr)也是四個字節,這樣輸出很方便. 
Vertex3d*array=new(str)Vertex3d;這條語句就是用了PON方法,在數組str中放置 
一個Vertex3d對象,一切都已經做好了,對象的布局就是在數組str中,不妨去看看 
str中的內容,這裡我就不打算把輸出結果寫出來了,自己調試.有個缺陷就是看不到 
virtual函數的函數地址(雖然有其他的方法,但不直觀.vc調試模式下直接就可以看,
或許我會想到辦法的) 
就簡單說這些了,vc編譯器的debug模式下可以直接看到的,更直觀,但我的 
目的只是弄懂c++類究竟是如何放置的(我不認為我是在轉牛角尖). 

(http://www.fanqiang.com)
    進入【UNIX論壇

相關文章
 

★  樊強制作 歡迎分享  ★