C++继承与派生

C++继承与派生,第1张

一.类的继承与派生:
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
*/

建立对象所指定的类称为最(远)派生类
虚基类的成员由最派生类调用虚基类的构造函数进行初始化,在初始化列表调用构造函数初始化。


虚函数与纯虚函数在多态进行总结

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/564690.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-06
下一篇 2022-04-06

发表评论

登录后才能评论

评论列表(0条)