第七章
1. 构造函数的继承
使用了cBase的构造方法对待ab,再自行对待c
cDerived::cDerived(int a, int b, int c) : cBase(a, b)
{
vc=c;
}
2. 静态结合&虚函数
声明了cBase的指针变量,但是指向了cDerive的类,那么即使使用
p->disp()
调用的也是cBase的
所以引入了虚函数virtual,在基类中声明,那么在p指向cDerived的时候,调用disp()函数,用的是继承类的disp()
注意
(1)指针声明的时候必须是一个基类的!
(2)两个函数有:
相同的函数名
相同的返回值
相同的参数个数/类型
(3)
函数只在基类存在,派生类无-->基类
只在派生类有,基类无-->错误
基类和派生类都不是virtual-->基类
基类和派生类都是virtual-->派生类
(4)
声明了子类的东西,去给父类赋值,指针,引用都可以实现多态,但是直接赋值不能
void main(void){
divide d; //派生类对象
base * b1=&d; //能实现多态
base & b2=d; //能实现多态
base b3=d; //不能实现多态
}
(5)
纯虚函数=0,不会(能)生成实体==>抽象类
纯虚函数必须在子类中给出声明
子类的指针可以是父类类型,但是不能相反. 指针换一个子类指的时候,必须强制转换 p=(cDerivedA *)&dtb;
析构函数也可以成为虚函数,子类的析构顺序是: 子析构==>父析构 ,没错,虚函数的父类析构也会执行
如果用new生成一个类的变量,不使用delete,main函数结束的时候并不会执行析构函数,因为new生成的是指针,不是变量
3. 虚类
考虑如下定义:
class cBase_A
{
public:
int getx( ){…}
……
};
class cBase_B: public cBase_A
{
……
};
class cBase_C: public cBase_A
{
……
};
class cDerived_D: public cBase_B, public cBase_C
{
……
};
cDerived_D x;
int A=x.getx( );//就不知道该用谁的,发生编译错误
//A=x.cBase_B::cBase_A::getx( );也是错的
所以引入了虚拟基类,在基类中声明为virtual
使用方法为class cDerived_B:virtual public cBase_A
这样的话,即使发生了分歧继承,也只会有一个基类的函数
非虚拟基类下:
每个基类数据成员互不影响
x.cBase_C::setx(11); x.cBase_B::setx(10);
看x.cBase_B::getx( )是10
看x.cBase_C::getx( );是11
虚拟基类就不会这样!
4. 多重继承的构造和析构
"根据class的具体顺序"
先生成父类
再生成自己的各个定义变量对象
最终生成自己
析构按照完全相反的方向
#include <iostream.h>
class innerA
{
public:
innerA( ){cout << "Entering innerA constructor.\n";}
~innerA( ){ cout << "Entering innerA destructor.\n";}
};
class innerB
{
public:
innerB( ){cout << "Entering innerB constructor.\n";}
~innerB( ){ cout << "Entering innerB destructor.\n";}
};
class baseC
{
innerA a;
public:
baseC ( ){cout << "Entering baseC constructor.\n";}
~ baseC ( ){ cout << "Entering baseC destructor.\n";}
};
class baseD
{
innerB b;
public:
baseD ( ){cout << "Entering baseD constructor.\n";}
~ baseD ( ){ cout << "Entering baseD destructor.\n";}
};
class outerA: public baseC, public baseD
{
innerA A1;
innerA A2;
innerB B1;
innerB B2;
public:
outerA( ){cout << "Entering outerA constructor.\n";}
~outerA( ){ cout << "Entering outerA destructor.\n";}
}
void main( )
{
outerA x;
}
执行之后:
Entering innerA constructor.
Entering baseC constructor.
Entering innerB constructor.
Entering baseD constructor.
Entering innerA constructor.
Entering innerA constructor.
Entering innerB constructor.
Entering innerB constructor.
Entering outerA constructor.
Entering outerA destructor.
Entering innerB destructor.
Entering innerB destructor.
Entering innerA destructor.
Entering innerA destructor.
Entering baseD destructor.
Entering innerB destructor.
Entering baseC destructor.
Entering innerA destructor.