第二十三節 C++ 如何禁止在棧中實例化類

有時需要在堆中創建對象,禁止在棧中去創建,

1 可以將析構函數定義爲private成員

2 建立static函數成員去delete這個堆空間

/* Human.h */
#include <string>    
/*
 * 爲了禁止某些類在棧中創建,措施之一是將析構函數定義爲private
 * 這樣在函數使用完對象,並對其銷燬時將出現錯誤,因爲不能在外部調用析構函數
 * 這種方式,堆內也是不可調用析構函數,delete也不可以使用, 導致內存泄露
 * 可以定義一個靜態函數,去delete這個堆空間
*/

/*此類中存在指針成員*/
class Human
{
private:
	char* name;  //指針指向一塊內存空間,要實現深複製防止兩個對象的指針指向同一個內存,非常危險  
	~Human();
	/*public類外可訪問*/
public:
	Human(const char* initString); //變量若不允許函數修改,最好定義成const變量  

	/*複製構造函數(實現深複製), 參數爲對象,爲個不淺複製對象,用引用或指針的方式傳參*/
	Human(const Human& Source);

	static void destoryInstance(Human* obj)
	{
		delete obj; //釋放堆空間
	}
	
};
/*Human.cpp*/
#include <iostream>    
#include <string>   
#include <string.h>  
#include "Human.h"    

Human::Human(const char* initString)
{
	std::cout << "1 call Human()" << std::endl;
	name = new char[strlen(initString) + 1];
}

Human::Human(const Human& source)
{
	std::cout << "2 call copy constructor function " << std::endl;
	name = new char[strlen(source.name) + 1]; //重新分配一個內存空間,保證兩個對象的指針成員不指向同一個內存空間  
	strncpy_s(name, strlen(source.name) + 1, source.name, strlen(source.name) + 1);
}

/*析構函數(對象被銷燬時被調用,類只有一個析構函數*/
Human::~Human()
{
	std::cout << "3 call ~Human()" << std::endl;
	delete name;
}

#include <iostream>    
#include "Human.h"    

int main()
{
	Human* man = new Human("aaaa"); //此處第一次調用構造函數    
	
	//delete man; //失敗,導致內存泄露
	man->destoryInstance(man);
	return 0;
}

輸出:

1 call Human()
3 call ~Human()


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章