最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解C++中如何將構(gòu)造函數(shù)或析構(gòu)函數(shù)的訪問權(quán)限定為private

 更新時間:2016年03月13日 17:09:41   作者:YoferZhang  
這篇文章主要介紹了詳解C++中如何將構(gòu)造函數(shù)或析構(gòu)函數(shù)的訪問權(quán)限定為private的方法,文中還解釋了構(gòu)造函數(shù)與虛函數(shù)的區(qū)別,需要的朋友可以參考下

今天面試被問到了這個單例模式常用到的技術(shù)手段,下面進行分析:
        很多情況下要求當前的程序中只有一個object。例如一個程序只有一個和數(shù)據(jù)庫的連接,只有一個鼠標的object。通常我們都將構(gòu)造函數(shù)的聲明置于public區(qū)段,假如我們將其放入private區(qū)段中會發(fā)生什么樣的后果?這意味著什么?
        當我們在程序中聲明一個對象時,編譯器為調(diào)用構(gòu)造函數(shù)(如果有的話),而這個調(diào)用將通常是外部的,也就是說它不屬于class對象本身的調(diào)用,假如構(gòu)造函數(shù)是私有的,由于在class外部不允許訪問私有成員,所以這將導致編譯出錯。
        然而,對于class本身,可以利用它的static公有成員,因為它們獨立于class對象之外,不必產(chǎn)生對象也可以使用它們。
        此時因為構(gòu)造函數(shù)被class私有化,所以我們要創(chuàng)建出對象,就必須能夠訪問到class的私有域;這一點只有class的成員可以做得到;但在我們建構(gòu)出其對象之前,怎么能利用它的成員呢?static公有成員,它是獨立于class對象而存在的,“我們”可以訪問得到。假如在某個static函數(shù)中創(chuàng)建了該class的對象,并以引用或者指針的形式將其返回(這里不以對象返回,主要是構(gòu)造函數(shù)是私有的,外部不能創(chuàng)建臨時對象),就獲得了這個對象的使用權(quán)。
下面是例子:

class OnlyHeapClass 
{ 
public: 
  static OnlyHeapClass* GetInstance() 
  { 
    // 創(chuàng)建一個OnlyHeapClass對象并返回其指針 
    return (new OnlyHeapClass); 
  } 
  void Destroy(); 
private: 
  OnlyHeapClass() { } 
  ~OnlyHeapClass() {} 
}; 
 
int main() 
{ 
  OnlyHeapClass *p = OnlyHeapClass::GetInstance(); 
  ... // 使用*p 
  delete p; 
  return 0; 
} 

 
        這個例子使用了私有構(gòu)造函數(shù),GetInstance()作為OnlyHeapClass的靜態(tài)成員函數(shù)來在內(nèi)存中創(chuàng)建對象:由于要跨函數(shù)傳遞并且不能使用值傳遞方式,所以我們選擇在堆上創(chuàng)建對象,這樣即使getInstance()退出,對象也不會隨之釋放,可以手動釋放。
        構(gòu)造函數(shù)私有化的類的設計保證了其他類不能從這個類派生或者創(chuàng)建類的實例,還有這樣的用途:例如,實現(xiàn)這樣一個class:它在內(nèi)存中至多存在一個,或者指定數(shù)量個的對象(可以在class的私有域中添加一個static類型的計數(shù)器,它的初值置為0,然后在GetInstance()中作些限制:每次調(diào)用它時先檢查計數(shù)器的值是否已經(jīng)達到對象個數(shù)的上限值,如果是則產(chǎn)生錯誤,否則才new出新的對象,同時將計數(shù)器的值增1.最后,為了避免值復制時產(chǎn)生新的對象副本,除了將構(gòu)造函數(shù)置為私有外,復制構(gòu)造函數(shù)也要特別聲明并置為私有。
        如果將構(gòu)造函數(shù)設計成Protected,也可以實現(xiàn)同樣的目的,但是可以被繼承。
        另外如何保證只能在堆上new一個新的類對象呢?只需把析構(gòu)函數(shù)定義為私有成員。
        原因是C++是一個靜態(tài)綁定的語言。在編譯過程中,所有的非虛函數(shù)調(diào)用都必須分析完成。即使是虛函數(shù),也需檢查可訪問性。因些,當在棧上生成對象時,對象會自動析構(gòu),也就說析構(gòu)函數(shù)必須可以訪問。而堆上生成對象,由于析構(gòu)時機由程序員控制,所以不一定需要析構(gòu)函數(shù)。保證了不能在棧上生成對象后,需要證明能在堆上生成它。這里OnlyHeapClass與一般對象唯一的區(qū)別在于它的析構(gòu)函數(shù)為私有。delete操作會調(diào)用析構(gòu)函數(shù)。所以不能編譯。
        那么如何釋放它呢?答案也很簡單,提供一個成員函數(shù),完成delete操作。在成員函數(shù)中,析構(gòu)函數(shù)是可以訪問的。當然detele操作也是可以編譯通過。

void OnlyHeapClass::Destroy() { 
  delete this; 
} 

        構(gòu)造函數(shù)私有化的類的設計可以保證只能用new命令在堆中來生成對象,只能動態(tài)的去創(chuàng)建對象,這樣可以自由的控制對象的生命周期。但是,這樣的類需要提供創(chuàng)建和撤銷的公共接口。
        另外重載delete,new為私有可以達到要求對象創(chuàng)建于棧上的目的,用placement new也可以創(chuàng)建在棧上。

補充:
1.為什么要自己調(diào)用呢?對象結(jié)束生存期時不就自動調(diào)用析構(gòu)函數(shù)了嗎?什么情況下需要自己調(diào)用析構(gòu)函數(shù)呢?  
        比如這樣一種情況,你希望在析構(gòu)之前必須做一些事情,但是用你類的人并不知道, 那么你就可以重新寫一個函數(shù),里面把要做的事情全部做完了再調(diào)用析構(gòu)函數(shù)。 這樣人家只能調(diào)用你這個函數(shù)析構(gòu)對象,從而保證了析構(gòu)前一定會做你要求的動作。

2.什么情況下才用得著只生成堆對象呢?
        堆對象就是new出來的,相對于棧對象而言。什么情況下要new,什么情況下在棧里面 提前分配,無非就是何時該用動態(tài),何時該用靜態(tài)生成的問題。這個要根據(jù)具體情況具體分析。比如你在一個函數(shù)里面事先知道某個對象最多只可能10個,那么你就可以 定義這個對象的一個數(shù)組。10個元素,每個元素都是一個棧對象。如果你無法確定數(shù) 字,那么你就可以定義一個這個對象的指針,需要創(chuàng)建的時候就new出來,并且用list 或者vector管理起來。

        類中“私有”權(quán)限的含義就是:私有成員只能在類域內(nèi)被訪問,不能在類域外進行訪問。

        把析構(gòu)函數(shù)定義為私有的,就阻止了用戶在類域外對析構(gòu)函數(shù)的使用。這表現(xiàn)在如下兩個方面:

        1. 禁止用戶對此類型的變量進行定義,即禁止在棧內(nèi)存空間內(nèi)創(chuàng)建此類型的對象。要創(chuàng)建對象,只能用 new 在堆上進行。

        2. 禁止用戶在程序中使用 delete 刪除此類型對象。對象的刪除只能在類內(nèi)實現(xiàn),也就是說只有類的實現(xiàn)者才有可能實現(xiàn)對對象的 delete,用戶不能隨便刪除對象。如果用戶想刪除對象的話,只能按照類的實現(xiàn)者提供的方法進行。

        可見,這樣做之后大大限制了用戶對此類的使用。一般來說不要這樣做;通常這樣做是用來達到特殊的目的,比如在 singleton 的實現(xiàn)上。

PS:構(gòu)造函數(shù)為什么不能是虛函數(shù)
另外再來說一下構(gòu)造函數(shù)和虛函數(shù)的區(qū)別:
       1. 從存儲空間角度,虛函數(shù)對應一個指向vtable虛函數(shù)表的指針,這大家都知道,可是這個指向vtable的指針其實是存儲在對象的內(nèi)存空間的。問題出來了,如果構(gòu)造函數(shù)是虛的,就需要通過 vtable來調(diào)用,可是對象還沒有實例化,也就是內(nèi)存空間還沒有,怎么找vtable呢?所以構(gòu)造函數(shù)不能是虛函數(shù)。
        2. 從使用角度,虛函數(shù)主要用于在信息不全的情況下,能使重載的函數(shù)得到對應的調(diào)用。構(gòu)造函數(shù)本身就是要初始化實例,那使用虛函數(shù)也沒有實際意義呀。所以構(gòu)造函數(shù)沒有必要是虛函數(shù)。虛函數(shù)的作用在于通過父類的指針或者引用來調(diào)用它的時候能夠變成調(diào)用子類的那個成員函數(shù)。而構(gòu)造函數(shù)是在創(chuàng)建對象時自動調(diào)用的,不可能通過父類的指針或者引用去調(diào)用,因此也就規(guī)定構(gòu)造函數(shù)不能是虛函數(shù)。
        3. 構(gòu)造函數(shù)不需要是虛函數(shù),也不允許是虛函數(shù),因為創(chuàng)建一個對象時我們總是要明確指定對象的類型,盡管我們可能通過實驗室的基類的指針或引用去訪問它但析構(gòu)卻不一定,我們往往通過基類的指針來銷毀對象。這時候如果析構(gòu)函數(shù)不是虛函數(shù),就不能正確識別對象類型從而不能正確調(diào)用析構(gòu)函數(shù)。
        4. 從實現(xiàn)上看,vbtl在構(gòu)造函數(shù)調(diào)用后才建立,因而構(gòu)造函數(shù)不可能成為虛函數(shù)從實際含義上看,在調(diào)用構(gòu)造函數(shù)時還不能確定對象的真實類型(因為子類會調(diào)父類的構(gòu)造函數(shù));而且構(gòu)造函數(shù)的作用是提供初始化,在對象生命期只執(zhí)行一次,不是對象的動態(tài)行為,也沒有必要成為虛函數(shù)。
        5. 當一個構(gòu)造函數(shù)被調(diào)用時,它做的首要的事情之一是初始化它的VPTR。因此,它只能知道它是“當前”類的,而完全忽視這個對象后面是否還有繼承者。當編譯器為這個構(gòu)造函數(shù)產(chǎn)生代碼時,它是為這個類的構(gòu)造函數(shù)產(chǎn)生代碼——既不是為基類,也不是為它的派生類(因為類不知道誰繼承它)。所以它使用的VPTR必須是對于這個類的VTABLE。而且,只要它是最后的構(gòu)造函數(shù)調(diào)用,那么在這個對象的生命期內(nèi),VPTR將保持被初始化為指向這個VTABLE, 但如果接著還有一個更晚派生的構(gòu)造函數(shù)被調(diào)用,這個構(gòu)造函數(shù)又將設置VPTR指向它的 VTABLE,等.直到最后的構(gòu)造函數(shù)結(jié)束。VPTR的狀態(tài)是由被最后調(diào)用的構(gòu)造函數(shù)確定的。這就是為什么構(gòu)造函數(shù)調(diào)用是從基類到更加派生類順序的另一個理由。但是,當這一系列構(gòu)造函數(shù)調(diào)用正發(fā)生時,每個構(gòu)造函數(shù)都已經(jīng)設置VPTR指向它自己的VTABLE。如果函數(shù)調(diào)用使用虛機制,它將只產(chǎn)生通過它自己的VTABLE的調(diào)用,而不是最后的VTABLE(所有構(gòu)造函數(shù)被調(diào)用后才會有最后的VTABLE)。

相關(guān)文章

  • 使用QGraphicsView實現(xiàn)氣泡聊天窗口+排雷功能

    使用QGraphicsView實現(xiàn)氣泡聊天窗口+排雷功能

    這篇文章主要介紹了使用QGraphicsView實現(xiàn)氣泡聊天窗口+排雷,重點給大家介紹使用QWebEngineView控件內(nèi)嵌html+CSS的實現(xiàn)方式,需要的朋友可以參考下
    2022-04-04
  • C語言 以數(shù)據(jù)塊的形式讀寫文件詳解及實現(xiàn)代碼

    C語言 以數(shù)據(jù)塊的形式讀寫文件詳解及實現(xiàn)代碼

    本文主要介紹 C語言 以數(shù)據(jù)塊的形式讀寫文件,這里對相關(guān)知識資料做了整理,并附代碼示例,以便大家學習參考,有學習此部分知識的朋友可以參考下
    2016-08-08
  • C++設計與實現(xiàn)ORM系統(tǒng)實例詳解

    C++設計與實現(xiàn)ORM系統(tǒng)實例詳解

    這篇文章主要為大家介紹了C++設計與實現(xiàn)ORM系統(tǒng)實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • OpenCV mask的作用及如何制作掩模mask

    OpenCV mask的作用及如何制作掩模mask

    mask 不是馬斯克,是掩膜,可以用來遮蓋非感興趣區(qū),突出感興趣區(qū),使得圖像處理只專注于ROI部分,OpenCV中的很多函數(shù)用到mask,mask是什么?怎么制作一個mask?本文給大家分享OpenCV mask的作用及如何制作掩模mask,感興趣的朋友一起看看吧
    2023-02-02
  • c++虛函數(shù)與虛函數(shù)表原理

    c++虛函數(shù)與虛函數(shù)表原理

    這篇文章主要介紹了c++虛函數(shù)與虛函數(shù)表原理,用virtual?修飾的成員函數(shù)叫虛函數(shù),下面圍繞c++虛函數(shù)與虛函數(shù)得相關(guān)資料展開內(nèi)容,需要的朋友可以參考一下
    2021-12-12
  • C++ 中回文數(shù)判斷簡單實例

    C++ 中回文數(shù)判斷簡單實例

    這篇文章主要介紹了C++ 中回文數(shù)判斷簡單實例的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • C++ string與int的相互轉(zhuǎn)換(使用C++11)

    C++ string與int的相互轉(zhuǎn)換(使用C++11)

    本文主要介紹了C++ string與int的相互轉(zhuǎn)換(使用C++11),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • C++中唯一三元運算符?:實例詳解

    C++中唯一三元運算符?:實例詳解

    這篇文章主要給大家介紹了關(guān)于C++中唯一三元運算符?:的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • 關(guān)于c語言的一個小bug詳解

    關(guān)于c語言的一個小bug詳解

    以下是對c語言中的一個小bug進行了詳細的分析介紹。需要的朋友可以過來參考下
    2013-08-08
  • 關(guān)于c語言中回調(diào)函數(shù)的理解

    關(guān)于c語言中回調(diào)函數(shù)的理解

    這篇文章主要給大家介紹了關(guān)于c語言中回調(diào)函數(shù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12

最新評論

尉氏县| 丰顺县| 焉耆| 固始县| 彩票| 云林县| 华坪县| 多伦县| 资源县| 山阴县| 迁西县| 长阳| 石林| 金昌市| 新蔡县| 怀柔区| 吕梁市| 丹东市| 景谷| 尼玛县| 龙川县| 徐闻县| 乡城县| 唐海县| 西昌市| 包头市| 谢通门县| 安康市| 修文县| 陆川县| 朝阳市| 建水县| 大悟县| 山西省| 云龙县| 托克托县| 扎兰屯市| 吴川市| 库车县| 仙居县| 金沙县|