c++中,物件的建立分為兩種,一種是靜態建立,如a a;另一種是動態建立,如 a *ptr=new a;
靜態建立:由編譯器為物件在棧上分配記憶體,是通過直接移動棧頂指標,挪出適當的空間,然後在這片記憶體空間上呼叫建構函式形成乙個棧物件,使用這種方法,直接呼叫類的建構函式
動態建立:是通過new運算子將物件建立在堆空間中,這個過程分為兩步,第一步是執行operator new()函式,在堆空間中搜尋合適的記憶體並進行分配,第二步是呼叫建構函式構造物件,初始化這片記憶體空間,這種方法,間接呼叫類的建構函式
接下來進行限制物件只能在那裡建立?
1.只能建立在堆上?
就是不能靜態的建立物件,即不能直接呼叫類的建構函式。
分析:(1)我們容易想到將建構函式設為私有,在建構函式私有之後,無法在類外部呼叫建構函式來構造類物件,只能使用new運算子來建立物件,然而,前面已經說過,new運算子的執行過程分為兩步,c++提供new運算子的過載,其實是只提供operator new() 函式,而operator()函式是進行記憶體分配的,無法提供構造功能,因此這種方法是不可以的
(2)物件建立在棧上面時,是由編譯器分配空間的,呼叫建構函式來構造棧物件,當物件使用完之後,編譯器會呼叫析構函式來釋放棧物件所佔的空間,編譯器管理了物件的整個生命週期,編譯器為物件分配空間的時候,只要是非靜態的函式都會檢查,包括析構函式,但是此時析構函式不可訪問,編譯器無法呼叫類的析構函式來釋放記憶體,那麼編譯器將無法在棧上為物件分配記憶體
classa
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()釋放記憶體
classa
void
destory()
protected
: a(){};
~a(){};
};
2.只能建立在棧上
只有使用new操作符,才會使物件建立在堆上,因此只要禁用new操作符就可以了,所以我們將operator new()操作符設為保護或者私有就可以了
classa; ~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就可...