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

2021-07-23 10:56:19 字數 1746 閱讀 7909

c++中,物件的建立分為兩種,一種是靜態建立,如a a;另一種是動態建立,如 a *ptr=new a;

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

動態建立:是通過new運算子將物件建立在堆空間中,這個過程分為兩步,第一步是執行operator new()函式,在堆空間中搜尋合適的記憶體並進行分配,第二步是呼叫建構函式構造物件,初始化這片記憶體空間,這種方法,間接呼叫類的建構函式

接下來進行限制物件只能在那裡建立?

1.只能建立在堆上?

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

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

(2)物件建立在棧上面時,是由編譯器分配空間的,呼叫建構函式來構造棧物件,當物件使用完之後,編譯器會呼叫析構函式來釋放棧物件所佔的空間,編譯器管理了物件的整個生命週期,編譯器為物件分配空間的時候,只要是非靜態的函式都會檢查,包括析構函式,但是此時析構函式不可訪問,編譯器無法呼叫類的析構函式來釋放記憶體,那麼編譯器將無法在棧上為物件分配記憶體

class

a

void

destory()

private

: ~a(){};

};

那可以嘗試使用a  b;來建立物件,編譯報錯,提示析構函式無法訪問,這樣就只能使用new來建立物件,建構函式是共有的,可以直接呼叫,但是類中必須通過destory()函式來進行記憶體的釋放,類物件使用完之後,必須呼叫destory()函式

上述方法兩個缺點:(1)無法解決繼承問題,因為通常情況之下a作為基類,一般析構函式要設為vitual,然後子類重寫,已實現多型,因此析構函式不能設為private,不過c++還有protected訪問控制方式,將析構函式設定為protected,這樣子類可以訪問,但是類外無法訪問。(2)使用不方便,不統一,因為你使用了new創造了物件,但是不能使用delete釋放物件,必須使用destory函式,這種方式比較怪異,所以我們也可以將建構函式設定為protected,同時提供另一public static create()函式來進行替代new。這樣  create()建立物件在堆上, destory()釋放記憶體

class

a

void

destory()

protected

: a(){};

~a(){};

};

2.只能建立在棧上

只有使用new操作符,才會使物件建立在堆上,因此只要禁用new操作符就可以了,所以我們將operator new()操作符設為保護或者私有就可以了

class

a; ~a(){};

protected

:

void* operator

new(size_t t){}; //

過載new,注意引數以及返回值

void

operator delete(void *ptr){}; //

過載了new,就要過載delete

};

保證只能在堆上new乙個類物件

有的時候為了保證乙個類的物件必須在堆上被建立,比如當我們需要手動控制乙個物件的生命週期的時候,這個時候就必須保證這個物件是在堆上建立的,如何保證呢,有個小的技巧 就是將析構函式給private了.並且用另外個公共函式來呼叫析夠函式.class a private a int main 原因是c 是乙...

設計乙個類,只能在堆上建立物件

設計乙個類 只能在堆上建立物件 思路 說明不能在棧上建立物件,考慮到棧上建立物件會發生哪些事 1 建構函式 2 拷貝構造 所以先遮蔽掉建構函式,即設為私有。存在問題 在堆上建立物件也會呼叫建構函式,設為私有對其有影響 解決 提供成員函式介面,在成員函式中建立堆物件。存在問題 成員函式需要物件來呼叫,...

只能在棧上或者堆上建立的物件

今天在這裡面看到了這個題目,據說還是google面試題。總的思想,是把一些在棧上或者堆上面建立物件,所必須的函式設為private使得編譯報錯。比如 只能在堆上建立,不能在棧上建立。因為棧上的物件,總是要呼叫析構函式。所以把析構函式設為private,然後new出來的物件,顯式的呼叫delete就可...