一.类的继承与派生:
1.继承与派生:保持已有类的特征构造新类的过程为继承,在已有类的基础上新增特性而产生新类的过程称为派生
2.继承目的:实现代码重用;派生目的:实现源程序的改造
3.声明:class 派生类:继承方式 基类
4.派生类:
吸收基类成员:派生类包含了基类中除了构造析构函数以外的所有成员,构造析构函数不会被继承
改造基类成员:虚函数重写(实际是虚函数表的覆盖)以及同名函数
添加新的成员:加入新的构造析构函数以及其他成员
二.类成员的访问:public--->protected--->private注意基类中私有成员不能被访问
基类中的私有成员派生类无法访问
继承方式为public时权限不变,但是私有成员也会被继承
继承方式为private何protected(体现类的继承特征)时,权限与继承方式一致
三.类型兼容规则:一个公有派生类的对象在使用上可以被当成基类的对象,反之不行
1.派生类的对象可以赋值给基类对象
2.派生类的对象可以初始化基类的引用
3.指向基类的指针可以指向派生类
通过基类的对象名与指针只能使用从基类继承的成员
#include
#include
using namespace std;
class Base
{
public:
void showBase()
{
cout << "base成员函数的调用" << endl;
}
};
class Son :public Base
{
public:
void showSon()
{
cout << "Son成员函数的调用" << endl;
}
};
int main()
{
Son s1;
Base b1 = s1;//派生类对象赋值给基类对象
Base& b2 = s1;//派生类对象初始化基类的引用
Base* b3 = &s1;//派生类地址初始化基类指针/基类指针指向派生类
b1.showBase();//通过基类的对象名和指针只能调用基类成员
b2.showBase();
b3->showBase();
return 0;
}
//运行结果:
//base成员函数的调用
//base成员函数的调用
//base成员函数的调用
四.单继承与多继承
1.单继承:一个基类一个派生类
2.多继承:多基类一派生 class 派生类:继承方式1 基类1, 继承方式2 基类2
3.多重派生:一个基类多个派生类
4.多层派生:派生类为基类继续派生
五.派生类的构造与析构
1.基类的构造析构函数不会被继承,派生类需要写自己的构造析构函数
2.派生类的构造函数需要给基类构造函数传递参数,注意基类成员用基类名在初始化列表进行初始化!!!
#include
#include
using namespace std;
class Base
{
public:
int m_A;
Base(int a):m_A(a){}//如果有默认构造,派生类构造时可以不传参
void showBase()
{
cout << "m_A=" << m_A << endl;
}
};
class Son :public Base
{
public:
int m_B;
Son(int a,int b):Base(a),m_B(b){}//注意基类用基类名在初始化列表进行初始化,多个基类类推
void showSon()
{
cout << "m_B="<
六.类成员的标识与访问
1.当派生类与基类成员同名时,优先调用派生类成员,基类同名成员被屏蔽(包括重载)
2.通过作用域来访问
#include
#include
using namespace std;
class Base
{
public:
int m_A;
Base(int a):m_A(a){}
void show()
{
cout << "基类m_A=" << m_A << endl;
}
void show(int a)
{
cout << "基类重载" << endl;
}
};
class Son :public Base
{
public:
int m_A;
Son(int a1,int a2):Base(a1),m_A(a2){}
void show()
{
cout << "派生类m_B="<
3.菱形继承引发的二义性问题:B1,B2继承A,C继承B1和B2,解决方法:同名屏蔽或虚函数
A类称为虚基类,在继承前加virtual,vbptr虚基类指针virtual base pointer指向虚基数表
#include
using namespace std;
class BaseA
{
public:
int m_A;
BaseA(int a):m_A(a){}
};
class BaseB1 :virtual public BaseA//虚继承
{
public:
int m_B1;
BaseB1(int a,int b1):BaseA(a),m_B1(b1){}
};
class BaseB2 :virtual public BaseA//虚继承
{
public:
int m_B2;
BaseB2(int a,int b2):BaseA(a),m_B2(b2){}
};
class SonC :public BaseB1, public BaseB2
{
public:
int m_C;
SonC(int a,int b1,int b2,int c):BaseA(a),BaseB1(a,b1),BaseB2(a,b2),m_C(c){}
};
int main()
{
SonC c(30,20,20,30);//B1,B2也可以初始化虚基类,但是C直接初始化优先级更高,调用了一次
cout << c.m_A << endl;
return 0;
}
//运行结果:30
/*
class BaseB1 size(12):
+---
0 | {vbptr}
4 | m_B1
+---
+--- (virtual base BaseA)
8 | m_A
+---
BaseB1::$vbtable@:
0 | 0
1 | 8 (BaseB1d(BaseB1+0)BaseA)
vbi: class offset o.vbptr o.vbte fVtorDisp
BaseA 8 0 4 0
*/
/*
class SonC size(24):
+---
0 | +--- (base class BaseB1)
0 | | {vbptr}
4 | | m_B1
| +---
8 | +--- (base class BaseB2)
8 | | {vbptr}
12 | | m_B2
| +---
16 | m_C
+---
+--- (virtual base BaseA)
20 | m_A
+---
SonC::$vbtable@BaseB1@:
0 | 0
1 | 20 (SonCd(BaseB1+0)BaseA)
SonC::$vbtable@BaseB2@:
0 | 0
1 | 12 (SonCd(BaseB2+0)BaseA)
vbi: class offset o.vbptr o.vbte fVtorDisp
BaseA 20 0 4 0
*/
建立对象所指定的类称为最(远)派生类
虚基类的成员由最派生类调用虚基类的构造函数进行初始化,在初始化列表调用构造函数初始化。
虚函数与纯虚函数在多态进行总结
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)