构造函数和复制控制成员不能继承,每个类定义自己的构造函数和复制控制成员,如果不自己定义,就将编译器自动合成。如果类需要只希望派生类使用的特殊构造函数,这样的构造函数应定义为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