OOP之继承篇
继承:
1、公有继承:
class A: public B
2、保护继承:
class A: protected B
3、私有继承:
class A: private B
protected在没有继承的情况下含义与private相同
公有继承:
子类public只能继承父类public部分
子类protected只能继承父类protected部分
子类可通过public函数访问protected属性
对于公有继承:
父类
private
成员——————————【子类不可访问】父类
protected
成员—————————【继承为子类protected成员】父类
public
成员——————————-【继承为子类public成员】
保护继承
对于保护继承:
父类
private
成员 ——————————-【子类不可访问】父类
protected
成员—————————-【继承为子类protected成员】父类
public
成员———————————【继承为子类protected成员】
私有继承
对于私有继承:
父类
private
成员 ——————————-【子类不可访问】父类
protected
成员—————————-【继承为子类private成员】父类
public
成员———————————【继承为子类private成员】
protected继承:子类只能访问到自己public下的数据成员、成员函数,而不能访问基类public下的数据成员、成员函数。
但是可以通过自己的成员函数访问到基类的数据成员及成员函数,也就是说不能直接访问。(因为这些数据成员及成员函数为private)
隐藏
子类覆盖父类同名成员函数,此时仍然可以访问父类的该函数
父子关系+成员函数同名,参数不同=隐藏
父子关系+成员函数同名,参数相同=覆盖
访问父类成员函数方法:child.Person::func();
(child表示对象,Person表示类,func为父子类同名的成员函数)
IS A关系
|
|
因为BOY是MAN的子集
子类对象赋值给父类对象时,父类对象只能获得二者共有的成员;对于父类指针指向子类对象的情况,指针只能访问共有的成员。
虚继承
菱形继承(含多继承、多重继承)->数据冗余->用虚继承解决数据冗余
>
维基百科虚继承
>
举例来说:假如类A和类B各自从类X派生(非虚继承且假设类X包含一些数据成员),且类C同时多继承自类A和B,那么C的对象就会拥有两套X的实例数据(可分别独立访问,一般要用适当的消歧义限定符)。但是如果类A与B各自虚继承了类X,那么C的对象就只包含一套类X的实例数据。
宏定义解决菱形重复引入定义的问题
在C++中,基类可以通过使用关键字virtual来
声明虚继承关系。
下文源自:关于C++中的虚拟继承的一些总结
1.为什么要引入虚拟继承
虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2,而类B1、B2都继承自类A,因此在类D中两次出现类A中的变量和函数。为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。实现的代码如下:
|
|
虚拟继承在一般的应用中很少用到,所以也往往被忽视,这也主要是因为在C++中,多重继承是不推荐的,也并不常用,而一旦离开了多重继承,虚拟继承就完全失去了存在的必要因为这样只会降低效率和占用更多的空间。
2.引入虚继承和直接继承会有什么区别呢
由于有了间接性和共享性两个特征,所以决定了虚继承体系下的对象在访问时必然会在时间和空间上与一般情况有较大不同。
2.1时间:
在通过继承类对象访问虚基类对象中的成员(包括数据成员和函数成员)时,都必须通过某种间接引用来完成,这样会增加引用寻址时间(就和虚函数一样),其实就是调整this指针以指向虚基类对象,只不过这个调整是运行时间接完成的。
2.2空间:
由于共享所以不必要在对象内存中保存多份虚基类子对象的拷贝,这样较之多继承节省空间。虚拟继承与普通继承不同的是,虚拟继承可以防止出现diamond继承时,一个派生类中同时出现了两个基类的子对象。也就是说,为了保证这一点,在虚拟继承情况下,基类子对象的布局是不同于普通继承的。因此,它需要多出一个指向基类子对象的指针。
C++ OOP特性还可参考本站其他相关博文: