通常構造函數/析構函數的聲明位於public區段,如果在private會有什么樣的后果?
那么,private構造函數怎么才能被用到呢?兩種方法:
1、使用友元類的對象中的方法來創建它。
2、在本類中實現static方法來創建它。
(1)構造函數定義private
在程序中實例化一個對象,編譯器將調用構造函數。如果構造函數是private,由於在class外部不允許訪問私有成員,將導致編譯失敗。
怎么解決這個問題呢?
對於類本身,可以利用static公有成員,因為它獨立於class對象之外,不必構造對象就可以使用它們!在某個static函數中創建該class的對象,並以引用或指針的形式將其返回(不以對象返回,主要是構造函數是私有的,外部不能創建臨時對象),就獲得了這個對象的使用權。
問題:
static成員函數貌似不可以訪問非static成員,為什么卻可以訪問私有的構造函數?
【實例】
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,也可以實現同樣的目的,但是可以被繼承。(當子類中的構造函數調用父類的private構造函數時會錯,當子類中的構造函數調用父類中的 public或protected構造函數時是對的。)
(2)析構函數private
如何保證只能在堆上new一個新的類對象呢?只需把析構函數定義為私有成員。
原因:
C++是一個靜態綁定的語言。在編譯過程中,所有的非虛函數調用都必須分析完成。即使是虛函數,也需檢查可訪問性。因些,當在棧上生成對象時,對象會自動析構,也就說析構函數必須可以訪問。
而堆上生成對象,由於析構時機由程序員控制,所以不一定需要析構函數。保證了不能在棧上生成對象后,需要證明能在堆上生成它。這里OnlyHeapClass與一般對象唯一的區別在於它的析構函數為私有。
那么如何釋放它呢?答案也很簡單,提供一個成員函數,完成delete操作。在成員函數中,析構函數是可以訪問的。當然detele操作也是可以編譯通過。
void OnlyHeapClass::Destroy() {
delete this;
}
構造函數私有化的類的設計可以保證只能用new命令在堆中來生成對象,只能動態的去創建對象,這樣可以自由的控制對象的生命周期。但是,這樣的類需要提供創建和撤銷的公共接口。
轉載:
http://www.blogjava.net/fhtdy2004/archive/2009/05/30/278971.html