如何定義乙個只能在堆上(棧上)生成物件的類

2021-08-05 21:35:03 字數 1738 閱讀 2798

在c++中,類的物件建立分為兩種:

靜態建立乙個類物件,是由編譯器為物件在棧空間分配記憶體,通過直接移動棧頂指標,挪出適當的空間,然後在這片記憶體空間上呼叫建構函式形成乙個棧物件。使用這種方法,直接呼叫類的建構函式。

動態建立類物件,是使用new 運算子將物件建立在堆空間中。這個過程分為兩步:

如何限制類物件只能在堆或棧上建立呢?下面分別討論:

類物件只能建立在堆上,就是不能靜態建立類物件,即不能直接呼叫類的建構函式。

容易想到將建構函式設為私有。在建構函式私有之後,無法在類外部呼叫建構函式來構造類物件,只能使用new運算子來建立物件。然而,前面已經說過,new運算子的執行過程分為兩步,c++提供new運算子的過載,其實是只允許過載operator new()函式,而operator new()函式用於分配記憶體,無法提供構造功能。因此,這種方法不可以。

當物件建立在棧上時,是由編譯器分配記憶體空間的,呼叫建構函式來構造棧物件,當物件使用完後,編譯器會呼叫析構函式來釋放棧物件所佔的空間。編譯器管理了物件的整個生命週期,如果編譯器無法呼叫析構函式來釋放物件,情況會是怎樣的呢?比如,類的析構函式是私有的,編譯器無法呼叫析構函式來釋放記憶體。所以,編譯器在為類物件分配棧空間時,會先檢查類的析構函式的訪問性,其實不光是析構函式,只要是非靜態的函式,編譯器都會進行檢查,如果類的析構函式是私有的,則編譯器不會在棧空間上位類物件分配空間。

因此,將析構函式設為私有,類物件就無法建立在站上了。**如下:

class a  

void destory()

private:

~a(){}

};

試著使用 a a;來建立物件,編譯出錯,提示析構函式無法訪問,這樣就只能使用new 操作符來建立物件,建構函式是公有的,可以直接呼叫。類中必須有乙個destroy函式,來進行記憶體空間的釋放,類物件使用完之後,必須呼叫destroy函式。

上述方法的乙個缺點就是,無法解決繼承問題,如果類a作為其他類的基類,則析構函式通常要設為virtual,然後在子類重寫,以實現多型。因此析構函式不能設為private,還好c++提供了第三種訪問控制protected,將析構函式設為protected可以有效解決這個問題,類外無法訪問protected成員,子類可以訪問;

另乙個問題是,類的使用很不方便,使用new建立物件,卻使用destory函式釋放物件,而不是使用delete。(使用delete會報錯,因為delete物件的指標,會呼叫物件的析構函式,而析構函式類外不可訪問)這種使用方式比較怪異。為了統一,可以將建構函式設為protected,然後提供乙個public的static函式完成構造,這樣不適用new,而是使用乙個函式來構造,使用乙個函式來析構,**如下,類似於單例模式:

class a

~a(){}

public:

static a* create()

void destroy()

};

這樣,呼叫create()函式在堆上建立類a物件,呼叫destroy()函式釋放記憶體;

只要使用new 運算子,物件才會建立在堆上,因此,只要禁用new運算子就可以實現類物件只能建立在棧上,將operator new()設為私有即可,**如下:

class a

void

operator

delete(void* ptr){}

public:

a(){}

~a(){}

};

如何定乙個只能在堆上或者只能在棧上定義的類

c 中,物件的建立分為兩種,一種是靜態建立,如a a 另一種是動態建立,如 a ptr new a 靜態建立 由編譯器為物件在棧上分配記憶體,是通過直接移動棧頂指標,挪出適當的空間,然後在這片記憶體空間上呼叫建構函式形成乙個棧物件,使用這種方法,直接呼叫類的建構函式 動態建立 是通過new運算子將物...

詳解如何定義乙個只能在堆上 棧上生成的類

相信有很多同學和我一樣都遇到過這個問題,而且都無處下手,在網上搜答案可能也看不太明白,今天重新回顧了一下這個知識點,感覺掌握起來其實不難,相信你看完這篇部落格 就能明白 1.如何定義乙個只能在堆上生成的類 方法一 首先我們要在堆上定義乙個物件的時候一定要用new 比如a a new a c 會先在堆...

如何定義乙個只能在堆上(棧上)生成物件的類

1 只能在堆上生成物件 將析構函式設定為私有。原因 c 是靜態繫結語言,編譯器管理棧上物件的生命週期,編譯器在為類物件分配棧空間時,會先檢查類的析構函式的訪問性。若析構函式不可訪問,則不能在棧上建立物件。2 只能在棧上生成物件 將new 和 delete 過載為私有。將new操作設定為私有,那麼第一...