c++类的继承解析

来源:互联网 发布:刷直通车淘宝抓吗 编辑:程序博客网 时间:2024/05/16 17:19

类的继承解析

         大家都知道C++有三大特性 ,它们分别是:封装性 ; 继承性  ;与多态性 。。。。


现 在来说说  ,类的继承性。。。。

之前稍微描述了一下类的基本概念 ,还有一些其他的特殊的类成员函数   。。。。那么、今天 就来向大家来解释一下类的继承特性。。。。

      一般情况下  、称父类为  基类    ,子类为派生类  

  继承  概念:

        面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能。这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。


说了这么多,简单说一下就是
1、代码的复用  ;

2、对于类对象的扩展;

3、简单--->复杂;



继承 的三种方式:


1、public  公有继承 ;

2、protected 保护继承 ;

3、private 私有继承 ;


继承的定义格式为   

 

派生类继承基类  ,会将基类的成员全部继承下来  ,包括  成员变量   还有成员函数。。。

在基类中成员的访问权限  ,在派生类中继承下来后  ,

在派生类中的访问权限变化为


(至于什么  protected  为保护访问权限。。。这种访问权限  的特性就是  ,声明的成员在派生类中 可以被访问

但是不能通过对象实例化来访问   。)

另外,在C++类继承 中  ,

public继承是一个接口继承,保持is-a原则,每个父类可用的成员对子类也可用,因为每个子类
对象也都是一个父类对象。

(可以用一句话来说就是 ,可以讲一个派生类对象当成是一个基类对象使用 )

(这个概念在类的赋值兼容规则中会得到成分的应用)

protectd/private继承是一个实现继承,基类的部分成员并非完全成为子类接口的一部分,
是 has-a 的关系原则,所以非特殊情况下不会使用这两种继承关系,在绝大多数的场景下使用的
都是公有继承。私有继承以为这is-implemented-in-terms-of(是根据……实现的)。通常比
组合(composition)更低级,但当一个派生类需要访问基类保护成员或需要重定义基类的虚函
数时它就是合理的。

(这个也可以  ,用一句话来判断就是 可以将 基类看成是派生类的一个成员  ,这个概念 和类的子对象有点相似,但还是有一些的区别的 )


派生类的基本成员函数

之前在以前的博客中就说过了 类的默认的成员函数有 6个 ,

它们非别是

构造函数 ;;

拷贝构造函数;;

赋值运算符的重载 ;;

析构函数;;

取地址操作符的重载  ;;

const修饰的取地址操作符的重载 ;;


但是在这里我们主要来说说    构造函数 与析构函数 。。。

【继承关系中    构造函数的调用顺序】

派生类的构造函数    ——》 在派生类的构造函数的初始化列表调用基类的构造函数  ——》派生类的构造函数体


【说明】
1、基类没有缺省构造函数,派生类必须要在初始化列表中显式给出基类名和参数列表。
2、基类没有定义构造函数,则派生类也可以不用定义,全部使用缺省构造函数。
3、基类定义了带有形参表构造函数,派生类就一定定义构造函数。


【继承关系中析构函数调用过程】


派生类的析构函数    ——》派生类所含成员的信息构函数   ——》基类的析构函数  


之后在这顺便提一下  、、、、、

如果  基类   含有    有显示定义   缺省的基类构造函数   ,那么   编译器 会默认为 派生类生成一个构造函数


如果  基类   含有     没有缺省的构造函数    ,那么 程序员必须明确出  派生类的构造函数 。

   

继承体系中的作用域变换 

1. 在继承体系中基类和派生类是两个不同作用域。
2. 子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可以
使用 基类::基类成员 访问)--隐藏 --重定义
3. 注意在实际中在继承体系里面最好不要定义同名的成员。



继承中  派生类的内存布局  

派生类的中的内存分布为  
                                                                          

派生类在调用构造函数后 要在 初始化列表中先调用 基类的构造函数  初始化一个基类对象

 ,然后 在函数 主体中 为派生类自己成员 赋值 。。。。。


所以 ,派生类的内存分布 为 先分配  一个 基类对象  ,之后再为 派生类成员分配空间 。。。

继承中的赋值兼容规则

派生类对象   可以   赋值给    基类 

基类对象    不可以 赋值给     派生类

基类的指针引用         可以            指向         派生类对象
派生类的指针引用      不可以         指向       基类对象(可以通过强制类型转换完成)

因为  根据 is -a  规则  可以将 一个派生类看成是 一个  基类

根据派生类的内存分布 , ,可以 将 派生类的前一部分看成一个  基类  ,将之赋值给基类对象  

但是不能讲  一个 基类对象  看成是一个派生类对象 

                                              

形象图显示


继承、友元、静态变量

类的继承性    继承的是类的成员 包括成员变量和成员函数,但是并不包括类的友元关系。。。。

举个例子来说明一下吧!!!!

class Date{friend void  fun();public :private:int _year;int _month;int _day;};class Time :public Date{ public:private:int _hour;int _minute;int _second;};void fun(){Date D;D._day = 1;D._month = 1;D._year = 2016;Time T;T._hour = 1;}

代码的错误报告

error C2248: “Time::_hour”: 无法访问 private 成员(在“Time”类中声明)
这说明Date类中友元函数fun()并没有在派生类Time中得到继承。。。


基类定义了static成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有
一个static成员实例。一句话说就是  继承的派生类任然可以在堆空间的静态区中访问


单继承&&多继承&&菱形继承

【单继承】

一个派生类只能有一个基类;;;;

形象图

                      


【多继承】

一个派生类可以有多个直接基类
形象图



【菱形继承】



菱形继承的对象模型

                                   


从图上我们就明显看出B 类对象声明了两个,,,,如果直接用D类对象调用B类成员就会产生二义性

所以只能先使用作用域限定符::进入C1或者C2作用域来调用B类对象,看上去很是繁琐,,,并且会造成冗余



所以就引进了虚拟继承的概念。。。。。

继承就先说的这了,,,,

之后再向大家详细介绍虚继承的概念












0 0