2)默认的复制构造函数逐个复制非静态成员(浅复制),复制的是成员的值。如果成员本身是类的对象,则将使用类的复制构造函数复制类的成员对象,静态函数不受影响,因为静态函数属于类本身,不属于任何一个类对象。这里需要注意的问题:对资源的复制。我们需要实现深度复制。比如说,Stack类对象ditto,该对象的str指向一块堆内存。现在利用它初始化另一个对象motto,这里如果简单的对其进行浅复制,则ditto.str和motto.str所保存的内存地址是同一块内存,这显然是不合适的。因此,这里我们应该在复制的同时给motto.str重新分配一块内存,然后将diito.str字符串复制过来,这实现了深度复制。
  Stack::Stack (const Stack & st)
  {
  int len  = strlen(st.str);
  str = new char[len + 1];
  str[len] = '';
  strcpy(str,st.str);
  }
  3、析构函数
  析构函数用来完成资源清理工作。一个类中只能有一个析构函数,且析构函数也可以没有返回值和声明类型,不带任何参数。
  需要注意的是,我们不应该在代码中显式的调用析构函数。如果调用的是静态存储类对象,则其析构函数将在程序结束时自动被调用。如果创建的是自动存储类对象,则其析构函数将在程序执行完代码块时自动被调用。此外,应注意析构函数和构造函数对堆资源的管理。用new申请的应该用delete释放,用new[]申请的应该使用delete[]释放。为了简单,建议都是用new[]和delete[]。
  4、赋值操作符
  函数原型如下:
  Class_name & Class_name::operator= (const Class_name &);
  将已有的对象赋值给另外一个对象,将使用重载赋值操作符。
  这里应该要弄清楚初始化和赋值的区别,不然不好弄清楚赋值操作符和复制构造函数的区别:赋值操作符所作用的两个对象都是已有的,而复制构造函数所作用的两个对象一个是已有的,一个是全新的。
  与复制构造函数类似,赋值操作符的隐式实现也对成员进行逐个复制,如果成员本身是类对象,则程序将使用为这个类定义的赋值操作符来复制该成员,但静态数据成员不受影响。同时,这里和复制构造函数有一个相似的问题,是对资源的开辟。
Stack & Stack::operator= (const Stack & st)
{
if (this == &st)
return *this;
delete[] str;
int len = strlen(st.str);
str = new char[len+1];
str[len] = '';
strcpy(str,st.str);
return *this;
}
  这里需要注意继承的问题,MSDN上有一句:
  All overloaded operators except assignment (operator=) are inherited by derived classes
  如果派生类中声明的成员与基类的成员同名,那么,基类的成员会被覆盖或隐藏,哪怕基类的成员与派生类的成员的数据类型和参数个数都完全不同。所以,“赋值运算符重载函数”不是不能被派生类继承,而是被派生类的默认“赋值运算符重载函数”给覆盖了。
  附上:重载、覆盖和隐藏的区别?
  函数的重载是指C++允许多个同名的函数存在,但同名的各个函数的形参必须有区别:形参的个数不同,或者形参的个数相同,但参数类型有所不同。
  覆盖(Override)是指派生类中存在重新定义的函数,其函数名、参数列、返回值类型必须同父类中的相对应被覆盖的函数严格一致,覆盖函数和被覆盖函数只有函数体 (花括号中的部分)不同,当派生类对象调用子类中该同名函数时会自动调用子类中的覆盖版本,而不是父类中的被覆盖函数版本,这种机制叫做覆盖,但要求有virtual关键字。
  隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
  1) 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
  2) 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。