日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

由创建一个不能被继承的类引发的对象模型的思考

發布時間:2025/3/21 编程问答 12 豆豆
生活随笔 收集整理的這篇文章主要介紹了 由创建一个不能被继承的类引发的对象模型的思考 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

昨天吃飯和寬妹討論起以前看過的如何創建一個不能被繼承的類,具體實現見

http://blog.csdn.net/kuaile123/article/details/21321471

同學提到了第一種方法,說new過之后還需要delete釋放內存,這樣需要把析構函數也設置為private。

然后就想到能不能創建一個變量,返回此變量,而不是new一個,這樣可以將析構函數設置為pubic不需要delete。寬妹說這種方法肯定行不通,因為這樣創建是在棧上創建的,當返回時變量已經無效了。事實證明是可行的。

class A{ private:int i;A( int j=0 ){ i=j; printf("construct: %d \n",i);} public:static A get_A0(){A a(2);return a;} }; A a0 = A::get_A0();//調用

后討論說他說的是返回變量的地址是有錯的,上述之所以成功是因為后面調用后使用了一個復制構造函數,這樣會造成效率低。然后再次寫了返回變量地址的方法,如下所示:

//class A 定義里面 public:static A* get_A1(){A a(2); return &a; }A* a1 = A::get_A1();//調用

顯示創建是沒用問題的,寬妹說調用此對象的一個成員函數肯定會出錯,由此,我們添加了一個成員函數,如下所示:

//class A 定義里面 public : int f(){printf("%d \n",i);return i;} //調用 a1->f();

輸出為:

construct: 2
4062396

而new的調用是這樣的:

static A* get_A2(){ return new A(3); } A* a2 = A::get_A2(); a2->f();

輸出為:

construct: 3
3

顯示堆上創建的調用是沒有錯的,棧上創建的調用結果是錯誤的。因為棧上創建的是局部變量,用new是在堆上創建的,如果不手動釋放會一直存在,而在棧上創建的出了作用域會失效,所以在堆上創建調用函數時沒有問題的。

但是依然可以打印說明仍然可以進入函數,但是只是打印成員數據時出錯,此時我們討論了C++對象模型,寬妹認為成員函數是不放置在類對象里的,而是經過混淆放置于一個全局的位置,所以雖然類對象是錯誤的,但是依然可以調用成員函數。為此又寫了一個調用方法來證實,將隨便一個變量的地址賦值給類對象,照樣能打印,數據還是此變量的值,如下所示:

int i =100;A* a = reinterpret_cast<A*>(&i);a->f();

輸出為:

100

由此可見沒有調用構造函數直接訪問了i的地址。我們翻了《C++對象模型》這本書,討論了出現這種結果的原因,C++對象模型中,只有非靜態數據成員被放置在每一個類對象中,而其他的如靜態數據成員、靜態和非靜態函數成員都是放置于類對象外,可以理解為一個類的空間中,每個對象只是共享同一份。這樣也就解釋了為什么類對象錯誤但是依然能夠調用類成員的原因。當創建一個類變量返回該變量的地址時,復制該指針,而當退出此函數時隨即此變量已經失效,a1指針實際上指向的是一塊無效的棧空間,當調用函數f()時,只是從類中調用,不經過類對象a1,f()中需要對象的數據成員i,就到認為正確的地址空間去找,a1+數據成員在a1中的偏移,而此時此段可能已經被改寫,此時不會返回正確的結果。同理,我們隨便將一個變量的地址強制轉換為類對象的指針,此時也是上述的流程,上述巧合是因為第一個聲明的成員變量地址和類對象地址是一致的,而且對象中的i和所聲明變量都是int型,讀取時都會讀取i的地址,當我們將變量設置為float等,此時就會有截斷等,打印出的也不是變量的值。


有些問題在書上看到過,但是距離用理論來分析還是有一定距離,幸而周圍有幾個小伙伴,尤其是寬妹,讓我對一些東西的理解更深一些。三個臭皮匠頂個諸葛亮,O(∩_∩)O哈哈~




 

總結

以上是生活随笔為你收集整理的由创建一个不能被继承的类引发的对象模型的思考的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。