继承方式与访问属性 多重继承和钻石继承 虚函数、覆盖 多态 虚构造和虚析构 纯虚函数和纯抽象类

继承方式与访问属性

访问控制属性决定了成员的访问范围:
    public      可以在任何位置访问
    private     只能在类内访问
    protected   只能在类内和子类中访问
继承方式的影响:
    1、父类的成员能否在子类中访问,是设计父类时访问控制属性决定的;继承方式能决定父类成员被子类继承后,在子类中变成什么样的访问控制属性,见下表:

        父类中属性	    public继承	        provite继承	        private继承
        public	       public	           protected	       private
        protected	   protected	       protected	       private
        private	       private	           private	           private

    2、只有以public方式继承父类,父类的指针或引用才可以指向子类对象(该语法是多态的基础)

多重继承和钻石继承

1、多重继承
    当一个类继承多个父类时,会按照继承表中的顺序在子类中排列父类,子类会标记每个父类的位置,当把子类指针转换成父类指针时,编译器会自动计算父类所在的位置,指针会自动偏移
2、钻石继承
    假如有一个类A,类B和类C都继承了类A,类D又继承了类B和类C,当子类的父类有共同的祖先,这种继承被称为钻石继承
    1、类B和类C中都有类A的内容
    2、类D会继承类B和类C中的所有内容,也就是说会继承两份类A中的内容
    3、当类D对象访问类A中的成员时,此时就会冲突,因为类A中的成员在类D中有多份,编译器无法区别就会出现编译错误
3、虚继承
    当使用 virtual 修饰继承时子类中会多出一个虚指针用于指向父类中的内容,当这个子类被继承时,孙子类会通过父类中的虚指针比较是否有多份祖先类,如果有多份则只保留一份
    这样的钻石继承在访问祖先成员时就不会冲突

虚函数、覆盖

1、当成员函数前加 virtual 关键字后,这样的函数就被称为虚函数,该类中就会像虚继承一样多了一个虚指针

2、虚函数表
    虚指针中记录的是一个表格的首地址,而该表格中记录了类中所有虚函数的地址
    ((void(*)(void))**(int**)p();   调用的就是虚函数表中的第一个虚函数

3、覆盖(重写)
    如果子类中有与父类虚函数同名的成员函数,编译器会比较这两个同名函数的格式;如果格式相同就把子类中同名的地址覆盖虚函数表中的记录(那么子类中的函数就会覆盖父类中的函数,这种情况就叫做函数覆盖或重写);如果不同则构成隐藏(子类隐藏·父类同名成员)

4、构成函数覆盖的条件
    1、在父子类之间
    2、父类中的函数为虚函数
    3、函数名、参数列表、常属性相同
    4、返回值类型相同,或者子类函数的返回值可以向父类函数的返回值做隐式转换(有继承关系)

多态

什么是多态:
    指的是指令的多种形态;当调用一个指令时,它能够根据参数、环境的不同做出相应的操作,这种情况就叫做多态
    根据确定操作的时间,多态分为:编译时多态,运行时多态
编译时多态:
    当调用重载函数,编译器根据参数的类型,在编译时就能确定执行哪个版本的重载函数;模板技术等
运行时多态:
    当子类覆盖了父类中的同名函数,然后父类指针或引用访问虚函数时,它即可能调用父类中函数也可能调用子类中函数,具体调用哪个版本时根据指针和引用的目标决定的,而这需要在运行期间才能确定,因此这种叫做运行时多态
构成运行时多态的条件:
    1、父子类之间有覆盖关系
    2、子类是以 public 方式继承的
    3、通过父类指针或引用访问虚函数

构造函数和析构函数是否可以是虚函数,为什么?

虚构造和虚析构

虚构造:
    构造函数不能是虚函数
    假如构造函数定义为虚函数,子类的构造函数就会自动覆盖父类的构造;当创建子类对象时,子类构造执行前会先调用父类构造,而父类对象已经被覆盖,此时会调用覆盖版本(子类构造),就会形成死循环,因此编译器把禁止构造函数定义为虚函数
虚析构:
    析构函数可以定义为虚函数
    当使用类多态时,通过父类指针或引用释放子类对象时,默认情况不会调用子类析构
    只有把父类的析构函数定义为虚函数(子类析构会自动覆盖它),当通过父类指针或引用释放子类对象时,会先调用子类的析构(多态),子类析构执行完成后会自动调用父类析构(继承的规则)
注意:当使用多态时且子类的析构函数中有需要释放的资源时,父类的析构函数一定要设置为虚析构

纯虚函数和纯抽象类

纯虚函数的格式:
    virtual 返回值 函数名(参数列表) = 0;
    1、纯虚函数可以不实现(一般人都不会去实现)
    2、有纯虚函数的类不能创建对象
    3、父类中如果有纯虚函数子类必须覆盖,否则也无法创建对象
    4、纯虚函数是强制子类实现某些功能的方法
    5、有纯虚函数的类叫抽象类
    6、析构函数不能定义为纯虚函数

纯抽象类:
    所有的成员函数都是纯虚函数,这种类叫纯抽象类,这种类一般用于设置功能接口,也叫做接口类型
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值