天天看點

面向對象之拷貝構造函數和指派函數之一

題:編寫類String的構造函數、析構函數和指派函數。【中國某著名綜合軟體公司2005年面試題】

答案:

已知類String的原型為:

class String
{
public:
	//普通構造函數
	String(const char *str = NULL);
	//拷貝構造函數
	String(const String &other);
	//析構函數
	~String(void);
	//指派函數
	String & operator=(const String &other);
private:
	//用于儲存字元串
	char *m_data;
};
           

編寫String的上述4個函數。

1、String的析構函數

為了防止記憶體洩漏,我們還需要定義一個析構函數。當一個String對象超出它的作用域時,這個析構函數将會釋放它所占用的資源。代碼如下:

String::~String()
{
	delete[] m_data;
	//由于m_data是内部資料類型,也可以寫成delete m_data;
}
           

2、String的構造函數

這個構造函數可以幫助我們根據一個字元串常量建立一個MyString對象。這個構造函數首先配置設定了足量的記憶體,然後把這個字元串常量複制到這塊記憶體,代碼如下:

String::String(const char *str)
{
	if(NULL == str)
	{
		m_data = new char[1];
		*m_data = '\0';
	}
	else
	{
		int length = strlen(str);
		m_data = new char[length+1];
		strcpy(m_data,str);
	}
}
           

strlen函數傳回這個字元串常量的實際字元數(不包括NULL終止符),然後把這個字元串常量的所有字元指派到我們在String對象建立過程中為m_data資料成員新配置設定的記憶體中。有了這個構造函數後,我們可以像下面這樣根據一個字元串常量建立一個新的String對象:

string str("hello");

3、String的拷貝構造函數

所有需要配置設定系統資源的使用者定義類型都需要一個拷貝構造函數,這樣我麼可以使用這個的聲明:

Mystring s1("hello");

Mystring s2 = s1;

拷貝構造函數還可以幫助我們在函數調用中以傳值方式傳遞一個Mystring參數,并且在當一個函數以值的形式傳回Mystring對象時實作“傳回時複制”。

String::String(const String &other)
{
	int length = strlen(other.m_data);
	m_data = new char[length+1];
	strcpy(m_data,other.m_data);
}
           

4、String的指派函數

指派函數可以實作字元串的傳值活動:

Mystring s1(“hello”);

Mystring s2;

s1 = s2;

代碼如下:

String & String::operator =(const String &other)
{
	if(this == &other)
	{
		return *this;
	}
	//釋放原有的記憶體資源
	delete[] m_data;
	//配置設定新的記憶體資源,并複制内容
	int length = strlen(other.m_data);
	m_data = new char[length+1];
	strcpy(m_data,other.m_data);
	//傳回本對象的引用
	return *this;
}