现在我们定义一个类
//name.h
class name
{
private:
char *str;
int len;
static in num_name; //全局变量,不能在声明中初始化。(因为声明描述了如何分配内存,但不分配内存)。
public:
name();
name(const char* s);
name(const name& s);
~name();
}
//name.cpp
#include <cstring>
#include <iostream>
using namespace std;
int name::num_name = 0;
name::name()
{
len = 4;
str = new char[len+1];
strcpy(str,"c++");
num_name ++‘
}
name::name(const char* s)
{
len = strlen(s);
str = new char[len+1];
strcpy(str, s);
num_name ++;
}
name::~name()
{
num_name--;
delete [] str;
}
我们把一个对象赋给另一个对象的时候会调用类的(默认的)隐式复制构造函数。默认的复制构造函数不说明其行为,因此它不指出创建过程,也不增加计数器的num_name的值,
但是析构函数更新了计数,并且在任何对象过期时都会被调用,而不管对象是如何被创建的。
所以,我们应该自己显示定义复制构造函数。
name::name(const name& s) //显示复制构造函数
{
num_name++;
............
}
下一个异常更微妙,隐式复制构造函数,是浅复制,对于指针类型相当于:对象A.str = 对象B.str,这种复制只是把B的字符串地址赋给A的字符串,这两个字符串指向同一字符串的同一地址,
对象A调用析构函数释放str,当对象B调用析构函数释放str的是已经被释放了的地址,这样会造成意想不到的错误,为了让对象都释放自己的字符串,所以要让对象都拥有自己的字符串,
我们要对字符串进行深度(deep)复制。
复制函数要这样写:
name::name(const name& s)
{
num_name ++;
len = s.len;
str = new char[len+1];
strcpy(str, s.str);
}
注意:如果类中包含了使用new初始化的指针成员,应当定义一个复制构造函数,以复制指向的数据,而不是指针,这被称为深度复制。复制的另一种形式(成员复制或浅复制)只是复制指针指,
浅复制仅浅浅的复制指针信息,而不会深入“挖掘”来复制指针引用的结构。