Bing Tree ,设计类的时候的三个特殊的函数:拷贝构造、拷贝赋值、析构函数
class String
{
public:
String (const char* cstr = 0);// 构造函数
String (const String& str); //拷贝构造
Strring& operator = (const String& str); //拷贝赋值(也是=的操作符重载)
~String(); //析构函数
privite:
char* m_data;
}
一、构造函数:
inline
String :: String(const char* cstr = 0)
{
if( cstr )
{
m_data = new char[ strlen(cstr) + 1 ];
strcpy(m_data, cstr);
}
else
{
m_data = new char[1];
*m_data = '\0';
}
}
构造函数(方法)是对象创建完成后第一个被对象自动调用的方法。它存在于每个声明的类中,是一个特殊的成员方法。作用是执行一些初始化的任务。
二、拷贝构造:
inline
String :: String(const String& str)
{
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
}
拷贝构造函数也是一种构造函数,它的作用是用已经建立的对象去初始化一个相同类型的对象。拷贝构造函数有三个用途:
- 用另外一个相同的对象初始化一个对象
- 拷贝一个对象传递给一个函数的参数
- 拷贝一个对象用来做一个函数的返回值
如果在一个类中没有定义拷贝构造函数,那么编译器会自动定义一个。如果类中有从堆中动态分配的指针变量,则类中必须定义拷贝构造函数
三、拷贝赋值:
inline String&
String :: operator = (const String& str)
{
if(this == &str) { return *this; }
delete [] m_data;
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
return *this;
}
与拷贝构造不同,拷贝赋值是用于对已经初始化的对象进行赋值。
需要注意的地方:
(1)因为作用对象本身就已经存在,所以必须先把自身的指针所指的内存空间给释放掉。
(2)因为使用者有可能会对自己进行赋值,而同一个对象,其m_data指针所指的位置相同,根据代码逻辑,会先释放自身的空间,因此接下来的操作会发生错误,因此有必要判断是否对自己赋值。
(3)返回对象无需考虑对方是以什么形式进行接收的。
四、析构函数:
inline
String :: ~String()
{
delete [] m_data;
}
(1)写法: ~tpyename()
(2)作用:与构造方法正好相反,是对象被销毁之前最后一个被对象自动调用的方法。是用于实现在销毁一个对象之前执行一些特定的操作,诸如关闭文件和释放内存等。由于这里是一个带指针的类,在对象销毁前还需要把指针所指的地址所占用的内存空间给释放掉,否则会造成内存泄露。