也是好久不寫了,忙著寫報告、忙著這這那那的破事,其實很多時候覺得作為一個程序猿甚至只是一個IT行業相關的人,能夠安心地、思路不被打亂地吃一本書
或是寫一段令自己滿意的代碼是一件多麼幸福的事情。直奔主題吧,C++的設計可謂是博大精深,有許多人因為這樣那樣的原因吐槽C++,然而在Inside The C++
Object Model一書中,作者Stanley B.Lippman展示了C++的一些看似令人費解的設計的原因,相信在了解這些原因以後,某些對C++存有偏見的人能夠理性地看
待C++的設計思想。這篇就主要記下最近的幾點收獲吧。
1.先來討論第一個關於繼承的小問題:
給定兩個類,class Point2d,class Point3d,Point3d由Point2d繼承而來,那麼Point3d中到底有多少個成員變量,5個還是3個?如果是5個,怎麼區分到底是從父類繼承的成員x、y還是自身的x、y?
Point3d: };
很簡單要確認這點,只用sizeof一下就行了,得到的答案是sizeof(Point3d)=20,這樣就可以確認是5個成員變量了,進一步實例化一個Point3d對象:
Point3d ptr;
使用ptr.x的方式(利用對象直接訪問),很明顯是調用的Point3d類型的成員x、而非Point2d的x成員,這是符合設計思想的(既然是特定唯一類的成員,當然取出的應該是這
個類特有的成員)。那要怎麼訪問從父類繼承的成員呢?
可以這樣:Point2d *pt = &ptr; //
pt->x;
此時訪問的就是從父類繼承的成員x。這樣就可以得出一個結論從父類繼承的成員變量的名稱和子類自身的成員變量名稱允許重復,並且這是兩個不同的成員。
class B:public virtual father{...};
class C:public A, public B{...};
則C對象中只保存一個father類對象。一個class如果內含virtual base class則將被分割為兩部分:一個不變區域和一個共享區域。不變區的數據為非虛基類的數據,而共享區就是虛基類數據。類中的虛函數表指針指向的虛函數表,正向偏移(向下)是尋址虛函數,負向偏移(向上)尋址的就是虛基類。還是以Point2d、Point3d類為例,Point3d由Point2d繼承而來,指針_vptr_Point3d指向虛函數表。
3.指向成員變量的指針
對於class Point3d的一個實例origin,&Point3d::z 和 &origin.z的結果是不同的,&Point3d::z應當為class Point3d內 member z的偏移量,而&origin.z 則為這個實例的member z 的地址。
然而在Microsoft Visual C++10.0下,下面幾條語句執行結果卻很奇特。
printf("%p\n",&Point3d::x);
printf("%p\n",&Point3d::y);
printf("%p\n",&Point3d::z);
cout<<&Point3d::x<<endl;
cout<<&Point3d::y<<endl;
cout<<&Point3d::z<<endl;
前三條分別為:0, 4 ,8 (已驗證,即為成員變量的偏移地址,在意料之中),書中寫在BCB3下結果分別為5,9,D,我沒有驗證;後三條結果均為1很奇特。合理的解釋只能是VC++有過特殊處理了。
好了就寫到這裡,繼續學習吧~