溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

c++怎么定義一個只能在堆或棧上生成對象的類

發(fā)布時間:2022-03-17 13:46:51 來源:億速云 閱讀:173 作者:iii 欄目:大數(shù)據(jù)

本篇內(nèi)容主要講解“c++怎么定義一個只能在堆或棧上生成對象的類”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“c++怎么定義一個只能在堆或棧上生成對象的類”吧!

在C++中,類的對象建立分為兩種:

  1. 一種是靜態(tài)建立,如A a;
  • 靜態(tài)建立一個類對象,是由編譯器為對象在??臻g中分配內(nèi)存,是通過直接移動棧頂指針,挪出適當?shù)目臻g,然后在這片內(nèi)存空間上調(diào)用構(gòu)造函數(shù)形成一個棧對象。使用這種方法,直接調(diào)用類的構(gòu)造函數(shù)。
  1. 一種是動態(tài)建立,如A* ptr=new A;這兩種方式是有區(qū)別的。
  • 動態(tài)建立類對象,是使用new運算符將對象建立在堆空間中。這個過程分為兩步,第一步是執(zhí)行operator new()函數(shù),在堆空間中搜索合適的內(nèi)存并進行分配;第二步是調(diào)用構(gòu)造函數(shù)構(gòu)造對象,初始化這片內(nèi)存空間。這種方法,間接調(diào)用類的構(gòu)造函數(shù)。 

1 只能在堆上

方法:將析構(gòu)函數(shù)設置為私有

原因:C++ 是靜態(tài)綁定語言,編譯器管理棧上對象的生命周期,編譯器在為類對象分配棧空間時,會先檢查類的析構(gòu)函數(shù)的訪問性。若析構(gòu)函數(shù)不可訪問,則不能在棧上創(chuàng)建對象。

思路:容易想到將構(gòu)造函數(shù)設為私有。在構(gòu)造函數(shù)私有之后,無法在類外部調(diào)用構(gòu)造函數(shù)來構(gòu)造類對象,只能使用new運算符來建立對象。然而,前面已經(jīng)說過,new運算符的執(zhí)行過程分為兩步,C++提供new運算符的重載,其實是只允許重載operator new()函數(shù),而operator()函數(shù)用于分配內(nèi)存,無法提供構(gòu)造功能。因此,這種方法不可以。

當對象建立在棧上面時,是由編譯器分配內(nèi)存空間的,調(diào)用構(gòu)造函數(shù)來構(gòu)造棧對象。當對象使用完后,編譯器會調(diào)用析構(gòu)函數(shù)來釋放棧對象所占的空間。編譯器管理了對象的整個生命周期。如果編譯器無法調(diào)用類的析構(gòu)函數(shù),情況會是怎樣的呢?比如,類的析構(gòu)函數(shù)是私有的,編譯器無法調(diào)用析構(gòu)函數(shù)來釋放內(nèi)存。所以,編譯器在為類對象分配棧空間時,會先檢查類的析構(gòu)函數(shù)的訪問性,其實不光是析構(gòu)函數(shù),只要是非靜態(tài)的函數(shù),編譯器都會進行檢查。如果類的析構(gòu)函數(shù)是私有的,則編譯器不會在??臻g上為類對象分配內(nèi)存。

將析構(gòu)函數(shù)設為私有,類對象就無法建立在棧上。

代碼

#include<iostream>
using namespace std;

//只在棧上開辟 2020.05.22
class A
{
public:
   A(){}
   void destory()
{
delete this;
}
private:
   ~A(){}
};

int main()
{

  A a;

 return 0;
}
 
c++怎么定義一個只能在堆或棧上生成對象的類  
使用A a建立對象,編譯報錯

提示析構(gòu)函數(shù)無法訪問。這樣就只能使用new操作符來建立對象,構(gòu)造函數(shù)是公有的,可以直接調(diào)用。類中必須提供一個destory函數(shù),來進行內(nèi)存空間的釋放。類對象使用完成后,必須調(diào)用destory函數(shù)。

上述方法的一個缺點就是,無法解決繼承問題。如果A作為其它類的基類,則析構(gòu)函數(shù)通常要設為virtual,然后在子類重寫,以實現(xiàn)多態(tài)。因此析構(gòu)函數(shù)不能設為private。還好C++提供了第三種訪問控制,protected。將析構(gòu)函數(shù)設為protected可以有效解決這個問題,類外無法訪問protected成員,子類則可以訪問。

另一個問題是,類的使用很不方便,使用new建立對象,卻使用destory函數(shù)釋放對象,而不是使用delete。(使用delete會報錯,因為delete對象的指針,會調(diào)用對象的析構(gòu)函數(shù),而析構(gòu)函數(shù)類外不可訪問)這種使用方式比較怪異。為了統(tǒng)一,可以將構(gòu)造函數(shù)設為protected,然后提供一個public的static函數(shù)來完成構(gòu)造,這樣不使用new,而是使用一個函數(shù)來構(gòu)造,使用一個函數(shù)來析構(gòu)。代碼如下,類似于單例模式:


#include<iostream>
using namespace std;

//只在棧上開辟 2020.05.22
class A
{
protected:
A(){}
~A(){}
public:
static A* create()
{
return new A();
}
void destory()
{
delete this;
}
};


int main()
{
A* ptr = A::create();
ptr->destory();
return 0;
}
 

這樣,調(diào)用create()函數(shù)在堆上創(chuàng)建類A對象,調(diào)用destory()函數(shù)釋放內(nèi)存。 

2 只能在棧上

方法:將 new 和 delete 重載為私有

原因:在堆上生成對象,使用 new 關鍵詞操作,其過程分為兩階段:第一階段,使用 new 在堆上尋找可用內(nèi)存,分配給對象;第二階段,調(diào)用構(gòu)造函數(shù)生成對象。將 new 操作設置為私有,那么第一階段就無法完成,就不能夠在堆上生成對象。

思路:只有使用new運算符,對象才會建立在堆上,因此,只要禁用new運算符就可以實現(xiàn)類對象只能建立在棧上。將operator new()設為私有即可。

代碼

class  A
{
private :
   void * operator  new ( size_t  t){}      // 注意函數(shù)的第一個參數(shù)和返回值都是固定的
   void  operator  delete ( void * ptr){}  // 重載了new就需要重載delete
public :
   A(){}
   ~A(){}
};
     

到此,相信大家對“c++怎么定義一個只能在堆或棧上生成對象的類”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關內(nèi)容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

c++
AI