C++堆對(duì)象如何禁用
C++中對(duì)于內(nèi)存的相關(guān)知識(shí)是一個(gè)比較重要而且復(fù)雜的知識(shí)點(diǎn),我們需要不斷的深入的對(duì)其進(jìn)行研究。今天在這里我們將會(huì)針對(duì)C++堆對(duì)象的一些應(yīng)用方法做一個(gè)詳細(xì)的介紹,應(yīng)該可以幫助大家對(duì)此有一個(gè)深刻的認(rèn)識(shí)。#t#
產(chǎn)生C++堆對(duì)象的方法是使用new操作,如果我們禁止使用new不就行了么。再進(jìn)一步,new操作執(zhí)行時(shí)會(huì)調(diào)用operator new,而operator new是可以重載的。方法有了,就是使new operator 為private,為了對(duì)稱,最好將operator delete也重載為private。
現(xiàn)在,你也許又有疑問了,難道創(chuàng)建棧對(duì)象不需要調(diào)用new嗎?是的,不需要,因?yàn)閯?chuàng)建棧對(duì)象不需要搜索內(nèi)存,而是直接調(diào)整堆棧指針,將對(duì)象壓棧,而operator new的主要任務(wù)是搜索合適的堆內(nèi)存,為C++堆對(duì)象分配空間,這在上面已經(jīng)提到過了。好,讓我們看看下面的示例代碼:
- #include stdlib.h 需要用到C式內(nèi)存分配函數(shù)
- class Resource ; 代表需要被封裝的資源類
- class NoHashObject
- {
- private
- Resource ptr ;指向被封裝的資源
- ... ... 其它數(shù)據(jù)成員
- void operator new(size_t size) 非嚴(yán)格實(shí)現(xiàn),僅作示意之用
- {
- return malloc(size) ;
- }
- void operator delete(void pp) 非嚴(yán)格實(shí)現(xiàn),僅作示意之用
- {
- free(pp) ;
- }
- public
- NoHashObject()
- {
- 此處可以獲得需要封裝的資源,并讓ptr指針指向該資源
- ptr = new Resource() ;
- }
- ~NoHashObject()
- {
- delete ptr ; 釋放封裝的資源
- }
- };
NoHashObject現(xiàn)在就是一個(gè)禁止C++堆對(duì)象的類了,如果你寫下如下代碼:
- NoHashObject fp = new NoHashObject() ; 編譯期錯(cuò)誤!
- delete fp ;
上面代碼會(huì)產(chǎn)生編譯期錯(cuò)誤。好了,現(xiàn)在你已經(jīng)知道了如何設(shè)計(jì)一個(gè)禁止堆對(duì)象的類了,你也許和我一樣有這樣的疑問,難道在類NoHashObject的定義不能改變的情況下,就一定不能產(chǎn)生該類型的C++堆對(duì)象了嗎?不,還是有辦法的,我稱之為“暴力破解法”。C++是如此地強(qiáng)大,強(qiáng)大到你可以用它做你想做的任何事情。這里主要用到的是技巧是指針類型的強(qiáng)制轉(zhuǎn)換。
- void main(void)
- {
- char temp = new char[sizeof(NoHashObject)] ;
強(qiáng)制類型轉(zhuǎn)換,現(xiàn)在ptr是一個(gè)指向NoHashObject對(duì)象的指針
- NoHashObject obj_ptr = (NoHashObject)temp ;
temp = NULL ; 防止通過temp指針修改NoHashObject對(duì)象
再一次強(qiáng)制類型轉(zhuǎn)換,讓rp指針指向堆中NoHashObject對(duì)象的ptr成員
- Resource rp = (Resource)obj_ptr ;
初始化obj_ptr指向的NoHashObject對(duì)象的ptr成員
- rp = new Resource() ;
現(xiàn)在可以通過使用obj_ptr指針使用堆中的NoHashObject對(duì)象成員了
- ... ...
- delete rp ;釋放資源
- temp = (char)obj_ptr ;
- obj_ptr = NULL ;防止懸掛指針產(chǎn)生
- delete [] temp ;釋放NoHashObject對(duì)象所占的堆空間。
- }
上面的實(shí)現(xiàn)是麻煩的,而且這種實(shí)現(xiàn)方式幾乎不會(huì)在實(shí)踐中使用,但是我還是寫出來路,因?yàn)槔斫馑?,?duì)于我們理解C++內(nèi)存對(duì)象是有好處的。對(duì)于上面的這么多強(qiáng)制類型轉(zhuǎn)換,其最根本的是什么了?我們可以這樣理解:
某塊內(nèi)存中的數(shù)據(jù)是不變的,而類型就是我們戴上的眼鏡,當(dāng)我們戴上一種眼鏡后,我們就會(huì)用對(duì)應(yīng)的類型來解釋內(nèi)存中的數(shù)據(jù),這樣不同的解釋就得到了不同的信息。
所謂強(qiáng)制類型轉(zhuǎn)換實(shí)際上就是換上另一副眼鏡后再來看同樣的那塊內(nèi)存數(shù)據(jù)。
另外要提醒的是,不同的編譯器對(duì)對(duì)象的成員數(shù)據(jù)的布局安排可能是不一樣的,比如,大多數(shù)編譯器將NoHashObject的ptr指針成員安排在對(duì)象空間的頭4個(gè)字節(jié),這樣才會(huì)保證下面這條語(yǔ)句的轉(zhuǎn)換動(dòng)作像我們預(yù)期的那樣執(zhí)行:
- Resource rp = (Resource)obj_ptr ;
但是,并不一定所有的編譯器都是如此。既然我們可以禁止產(chǎn)生某種類型的C++堆對(duì)象,那么可以設(shè)計(jì)一個(gè)類,使之不能產(chǎn)生棧對(duì)象嗎?當(dāng)然可以。