程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 詳解C++中若何將結構函數或析構函數的拜訪權限制為private

詳解C++中若何將結構函數或析構函數的拜訪權限制為private

編輯:關於C++

詳解C++中若何將結構函數或析構函數的拜訪權限制為private。本站提示廣大學習愛好者:(詳解C++中若何將結構函數或析構函數的拜訪權限制為private)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解C++中若何將結構函數或析構函數的拜訪權限制為private正文


明天面試被問到了這個單例形式經常使用到的技巧手腕,上面停止剖析:
        許多情形下請求以後的法式中只要一個object。例如一個法式只要一個和數據庫的銜接,只要一個鼠標的object。平日我們都將結構函數的聲明置於public區段,假設我們將其放入private區段中會產生甚麼樣的效果?這意味著甚麼?
        當我們在法式中聲明一個對象時,編譯器為挪用結構函數(假如有的話),而這個挪用將平日是內部的,也就是說它不屬於class對象自己的挪用,假設結構函數是公有的,因為在class內部不許可拜訪公有成員,所以這將招致編譯失足。
        但是,關於class自己,可以應用它的static私有成員,由於它們自力於class對象以外,不用發生對象也能夠應用它們。
        此時由於結構函數被class公有化,所以我們要創立出對象,就必需可以或許拜訪到class的公有域;這一點只要class的成員可以做獲得;但在我們建構出其對象之前,怎樣能應用它的成員呢?static私有成員,它是自力於class對象而存在的,“我們”可以拜訪獲得。假設在某個static函數中創立了該class的對象,並以援用或許指針的情勢將其前往(這裡不以對象前往,重要是結構函數是公有的,內部不克不及創立暫時對象),就取得了這個對象的應用權。
上面是例子:

class OnlyHeapClass 
{ 
public: 
  static OnlyHeapClass* GetInstance() 
  { 
    // 創立一個OnlyHeapClass對象並前往其指針 
    return (new OnlyHeapClass); 
  } 
  void Destroy(); 
private: 
  OnlyHeapClass() { } 
  ~OnlyHeapClass() {} 
}; 
 
int main() 
{ 
  OnlyHeapClass *p = OnlyHeapClass::GetInstance(); 
  ... // 應用*p 
  delete p; 
  return 0; 
} 

 
        這個例子應用了公有結構函數,GetInstance()作為OnlyHeapClass的靜態成員函數來在內存中創立對象:因為要跨函數傳遞而且不克不及應用值傳遞方法,所以我們選擇在堆上創立對象,如許即便getInstance()加入,對象也不會隨之釋放,可以手動釋放。
        結構函數公有化的類的設計包管了其他類不克不及從這個類派生或許創立類的實例,還有如許的用處:例如,完成如許一個class:它在內存中至少存在一個,或許指定命量個的對象(可以在class的公有域中添加一個static類型的計數器,它的初值置為0,然後在GetInstance()中作些限制:每次挪用它時先檢討計數器的值能否曾經到達對象個數的下限值,假如是則發生毛病,不然才new出新的對象,同時將計數器的值增1.最初,為了不值復制時發生新的對象正本,除將結構函數置為公有外,復制結構函數也要特殊聲明並置為公有。
        假如將結構函數設計成Protected,也能夠完成異樣的目標,然則可以被繼續。
        別的若何包管只能在堆上new一個新的類對象呢?只需把析構函數界說為公有成員。
        緣由是C++是一個靜態綁定的說話。在編譯進程中,一切的非虛函數挪用都必需剖析完成。即便是虛函數,也需檢討可拜訪性。因些,當在棧上生成對象時,對象會主動析構,也就說析構函數必需可以拜訪。而堆上生成對象,因為析構機會由法式員掌握,所以紛歧定須要析構函數。包管了不克不及在棧上生成對象後,須要證實能在堆上生成它。這裡OnlyHeapClass與普通對象獨一的差別在於它的析構函數為公有。delete操作會挪用析構函數。所以不克不及編譯。
        那末若何釋放它呢?謎底也很簡略,供給一個成員函數,完成delete操作。在成員函數中,析構函數是可以拜訪的。固然detele操作也是可以編譯經由過程。

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

        結構函數公有化的類的設計可以包管只能用new敕令在堆中來生成對象,只能靜態的去創立對象,如許可以自在的掌握對象的性命周期。然則,如許的類須要供給創立和撤消的公共接口。
        別的重載delete,new為公有可以到達請求對象創立於棧上的目標,用placement new也能夠創立在棧上。

彌補:
1.為何要本身挪用呢?對象停止生計期時不就主動挪用析構函數了嗎?甚麼情形下須要本身挪用析構函數呢?  
        好比如許一種情形,你願望在析構之前必需做一些工作,然則用你類的人其實不曉得, 那末你便可以從新寫一個函數,外面把要做的工作全體做完了再挪用析構函數。 如許人家只能挪用你這個函數析構對象,從而包管了析構前必定會做你請求的舉措。

2.甚麼情形下才用得著只生成堆對象呢?
        堆對象就是new出來的,絕對於棧對象而言。甚麼情形下要new,甚麼情形下在棧外面 提早分派,不過就是什麼時候該用靜態,什麼時候該用靜態生成的成績。這個要依據詳細情形詳細剖析。好比你在一個函數外面事前曉得某個對象最多只能夠10個,那末你便可以 界說這個對象的一個數組。10個元素,每一個元素都是一個棧對象。假如你沒法肯定數 字,那末你便可以界說一個這個對象的指針,須要創立的時刻就new出來,而且用list 或許vector治理起來。

        類中“公有”權限的寄義就是:公有成員只能在類域內被拜訪,不克不及在類域外停止拜訪。

        把析構函數界說為公有的,就阻攔了用戶在類域外對析構函數的應用。這表示在以下兩個方面:

        1. 制止用戶對此類型的變量停止界說,即制止在棧內存空間內創立此類型的對象。要創立對象,只能用 new 在堆長進行。

        2. 制止用戶在法式中應用 delete 刪除此類型對象。對象的刪除只能在類內完成,也就是說只要類的完成者才有能夠完成對對象的 delete,用戶不克不及隨意刪除對象。假如用戶想刪除對象的話,只能依照類的完成者供給的辦法停止。

        可見,如許做以後年夜年夜限制了用戶對此類的應用。普通來講不要如許做;平日如許做是用來到達特別的目標,好比在 singleton 的完成上。

PS:結構函數為何不克不及是虛函數
別的再來講一下結構函數和虛函數的差別:
       1. 從存儲空間角度,虛函數對應一個指向vtable虛函數表的指針,這年夜家都曉得,可是這個指向vtable的指針實際上是存儲在對象的內存空間的。成績出來了,假如結構函數是虛的,就須要經由過程 vtable來挪用,可是對象還沒有實例化,也就是內存空間還沒有,怎樣找vtable呢?所以結構函數不克不及是虛函數。
        2. 從應用角度,虛函數重要用於在信息不全的情形下,能使重載的函數獲得對應的挪用。結構函數自己就是要初始化實例,那應用虛函數也沒有現實意義呀。所以結構函數沒有需要是虛函數。虛函數的感化在於經由過程父類的指針或許援用來挪用它的時刻可以或許釀成挪用子類的誰人成員函數。而結構函數是在創立對象時主動挪用的,弗成能經由過程父類的指針或許援用去挪用,是以也就劃定結構函數不克不及是虛函數。
        3. 結構函數不須要是虛函數,也不許可是虛函數,由於創立一個對象時我們老是要明白指定對象的類型,雖然我們能夠經由過程試驗室的基類的指針或援用去拜訪它但析構卻紛歧定,我們常常經由過程基類的指針來燒毀對象。這時候候假如析構函數不是虛函數,就不克不及准確辨認對象類型從而不克不及准確挪用析構函數。
        4. 從完成上看,vbtl在結構函數挪用後才樹立,因此結構函數弗成能成為虛函數從現實寄義上看,在挪用結構函數時還不克不及肯定對象的真實類型(由於子類會調父類的結構函數);並且結構函數的感化是供給初始化,在對象性命期只履行一次,不是對象的靜態行動,也沒有需要成為虛函數。
        5. 當一個結構函數被挪用時,它做的重要的工作之一是初始化它的VPTR。是以,它只能曉得它是“以後”類的,而完整疏忽這個對象前面能否還有繼續者。當編譯器為這個結構函數發生代碼時,它是為這個類的結構函數發生代碼——既不是為基類,也不是為它的派生類(由於類不曉得誰繼續它)。所以它應用的VPTR必需是關於這個類的VTABLE。並且,只需它是最初的結構函數挪用,那末在這個對象的性命期內,VPTR將堅持被初始化為指向這個VTABLE, 但假如接著還有一個更晚派生的結構函數被挪用,這個結構函數又將設置VPTR指向它的 VTABLE,等.直到最初的結構函數停止。VPTR的狀況是由被最初挪用的結構函數肯定的。這就是為何結構函數挪用是從基類到加倍派生類次序的另外一個來由。然則,當這一系列結構函數挪用正產生時,每一個結構函數都曾經設置VPTR指向它本身的VTABLE。假如函數挪用應用虛機制,它將只發生經由過程它本身的VTABLE的挪用,而不是最初的VTABLE(一切結構函數被挪用後才會有最初的VTABLE)。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved