標籤:namespace 刪除 -o 建立 最好 cout cpp 測試 需要
在C++中,為了讓某個類只能通過new來建立(即如果直接建立對象,編譯器將報錯),應該()
正確答案: B 你的答案: D (錯誤)
將建構函式設為私人
將解構函式設為私人
將建構函式和解構函式均設為私人
沒有辦法能做到
當時沒有多想,覺得不太可能。事後想起來才發現這很容易做到,實質上還是記憶體管理的問題。
只能做堆上建立對象
在C++中,類的建立分為兩種。一種是靜態建立,即直接建立對象;另一種是動態建立對象,即通過 new 建立,如 T *t = new T。要想正確回答上題,就必須知道這兩種建立方式的區別。
1 靜態建立
由編譯器在棧中為對象分配記憶體,通過移動棧頂指標獲得合適大小的空間,然後調用對象的建構函式產生對象。
2 動態建立
通過new在堆中建立對象。這個過程分為兩步:首先在堆中找到合適大小的空間並分配,然後調用對象的建構函式產生對象。
因為兩者都需要調用對象的建構函式,所以通過將建構函式私人化的做法是行不通的。那麼還有其他辦法嗎?這是就需要瞭解靜態建立的另一個特點了。
編譯器在為類對象分配棧空間時,會先檢查類的解構函式的訪問性,其實不光是解構函式,只要是非靜態函數,編譯器都會進行檢查。如果類的解構函式是私人的,則編譯器不會在棧空間上為類對象分配記憶體。
所以我們只需要將解構函式私人化就可以組織直接建立對象了。由於棧的建立和釋放都需要由系統完成的,所以若是無法調用構造或者解構函式,自然會報錯。
當然為了我們能夠正確釋放動態建立的對象,我們必須提供一個公有函數,該函數的唯一功能就是刪除對象本身。
測試代碼如下:
#include<iostream>using namespace std;class test{private:~test(){ cout << "test destroy" << endl; }public:void destroy(){delete this;}};int main(){//test p;//編譯器報錯test::~test()不可訪問test *p = new test;p->destroy();}
只能在棧上建立對象 既然可以做到只在堆上建立對象,同樣的我們可以只在棧上建立對象。其實理解了這個理念,不難想到我們只需要
讓new操作符無法使用即可,要做到這件事,我們可以將
new操作符重載並設定為私人訪問即可。是不是很巧妙的方法~
重載new的同時最好重載delete
#include<iostream>using namespace std;class test{private:void* operator new(size_t t){}void operator delete(void* ptr){}public:~test(){cout << "test destroy" << endl;}};int main(){//test *A = new test;//編譯器報錯函數test::operator new 不可訪問test A;
上面是在堆上動態建立,下面是在棧上靜態建立
}
C++中兩種建立對象的方式