读书笔记--构造函数和复制控制

来源:互联网 发布:非零矩阵 编辑:程序博客网 时间:2024/05/18 20:09

  构造函数和复制控制成员不能继承,每个类定义自己的构造函数和复制控制成员,如果不自己定义,就将编译器自动合成。如果类需要只希望派生类使用的特殊构造函数,这样的构造函数应定义为protected。
  派生类的合成默认构造函数的初始化时:
1.先调用派生类上一级的默认构造函数初始化
2.然后初始化本垒的数据成员

class Bulk_item:public Item_base
{
 public:
  Bulk_itm():min_qty(0),discount(0.0){}
};
隐式调用Item_base的默认构造函数

向基类构造函数传递实参(初始化)
class Bulk_itm:public Item_base
{
 public:
  Bulk_item(const string &book,double sales_price,size_t qty=0,/
         double disc_rate=0.0):Item_base(book,sales_item),min_qty/
         (qty),discount(disc_rate){}
};
一个类只能初始化直接基类,而不能跨越初始化

  派生类的賦值操作符:若派生类自定义了自己的賦值操作符,则该操作必须对基类部分进行显示賦值
Derived &Derived::operator=(const Derived &rhs)
{
 if(this!=&rhs)    //防止自身复制
 {
  Base::operator=(rhs);   //assigned the base part
 }
 return *this;
}

  派生类析构函数不负责撤销基类对象的成员,对象的撤销顺序与构造顺序相反,首先运行派生类析构函数,然后按照继承层次一次向上调用各级类析构函数
  如果删除基类指针,则需要运行基类析构函数并清除基类的成员。如果对象实际上是派生类型,则没有定义该行动。故基类的析构函数应为虚函数,当析构函数为虚函数时,通过指针调用,运行哪个析构函数将返回指针对象类型的不同而不同(析构函数的性质将继承)
class Item_base
{
 public:
  //no work,but virtual destuctor needed
  //if base pointer that points to a derived object is ever deleted
  virtual ~Item_base(){}
};
Item_base *itemp=new Item_base;           //same static and dynamic type
delete itemp;         //Ok:destructor for Item_base called
itemp=new Bulk_item;        //Ok:static and dynameic type differ
deleted itemp;         //Ok:destructor for Bulk_item called
在复制控制成员中,只有析构函数定义为虚函数,其他不应定义为虚函数(构造,賦值) ,因为在每个类中都有自己的复制控制成员.
 
  如果派生类想通过自身类型使用所有的重载版本,则派生类必须冲定义所有重载版本,要么一个也不重定义,因为派生类成员会屏蔽积累中相同名字的成员
  派生类也可以不用重定义所继承的每一个基类版本,可以为重载成员函数名称而作的using声明,将该函数的所有重载实例加到派生的作用域
  要获得动态绑定,必须通过基类的引用或指针调用虚成员,虚函数在基类和派生类中拥有同一原型。如果不相同,则没办法通过基类类型的引用或指针引用派生类函数
class Base
{
 public: 
  virtual int fcn();
};
class D1:public Base
{
 public:
  int fcn(int);      //hides fcn in the base
};
class D2:public D1
{
 public:
  int fcn(int);     //nonvirtual function D1:fcn(int)
  int fcn();        //redefines virtual fcn from Base
};
Base bobj;
D1 d1obj;
D2 d2obj;
Base *bp1=&bobj,*bp2=&d1.obj,*bp3=&d2obj;
bp1->fcn();            //OK will call Base::fcn at run time
bp2->fcn();      //OK will call Base::fcn at run time
bp3->fcn();      //OK will call Base::fcn at run time