派生类构造函数
派生类的构造函数受继承关系的影响,每个派生类构造函数除了初始化自己的数据成员之外,还要初始化基类,也会运行基类的构造函数 。
#include "stdafx.h"
#include <iostream>
using namespace std;
class Ctest
{
public:
Ctest(int a=1,int b=2,int c=3){
cout<<"基类构造函数"<<endl;
}
};
class TDer: public Ctest
{
public:
TDer(){cout<<"派生类构造函数"<<endl;}
};
int _tmain(int argc, _TCHAR* argv[])
{
TDer a;
return 0;
}
运行结果:基类构造函数,派生类构造函数
先运行基类构造函数,在运行派生类构造函数。
派生类构造函数的初始化列表只能初始化派生类的成员,不能直接初始化继承成员。相反,派生类构造函数通过将基类包含在构造函数初始化列表中来间接初始化继承成员。
只能初始化直接基类。直接基类就是在派生列表中指定的类。
关键概念:尊重基类接口
构造函数只能初始化其直接基类的原因是每个类都定义了自己的接口.定义了ClassB时候,通过定义它的构造函数制定了怎样初始化ClassB对象。一旦类定义了自己的接口,与该类对象的所有交互都应该通过该接口,即使对象是派生类对象的一部分也不例外。
同样,派生类构造函数不能通过初始化基类的成员且不应该对基类成员赋值。如果那些成员为public或protected,派生构造函数可以在构造函数函数体中给基类成员赋值,但是,这样会违反基类的接口。派生类应该通过使用基类构造函数尊重基类的初始化意图,而不是在派生类构造函数函数体中对这些成员赋值。
复制控制和继承
定义派生类复制构造函数.
简单:就是先显示调用基类的复制构造函数初始化对象的基类部分.然后再对派生类的部分进行复制.
同样.派生类赋值操作符也是同样的处理方法
显示调用基类部分的赋值.然后再对派生类的进行赋值.
派生类析构函数则不一样
派生类析构函数不负责撤销基类对象的成员。编译器总是显示的调用派生类对象基类部分的析构函数。每个析构函数值负责清除自己的成员.
对象的撤销顺序与构造顺序相反:首先运行派生类析构函数,然后按继承层次依次向上调用各基类析构函数.
注意,不要将赋值操作符设为虚函数,因为很可能令人混淆,而且不会得到什么好处。
因为虚函数必须在基类和派生类中具有同样的形参。基类赋值操作符有一个形参是自身类类型的引用,如果该操作符为虚函数,则每个类都将得到一个虚函数成员,该成员定义了参数为一个基类对象的operator=.但是,对派生类而言,这个操作符与赋值操作符是不同的。
注意:基类类型的指针(引用或对象)只能访问对喜爱那个的基类部分,而在基类中没有定义派生类中的一些行为.比如
Bulk_item bulk;
Bulk_item *bulkP= &bulk;
Item_base *itemP = &bulk;
bulkP -> discount_policy();
itemP -> discount_policy();//错误...
因为在Item_base里面没有这个方法discount_policy();
设计派生类的时候,只要可能,最好避免与基类成员的名字冲突。