c++ d14

将派生类对象转换为基类对象

1.可以将派生类对象赋值给基类对象
2.可以将基类的引用绑定到派生类的对象
3.可以将基类的指针指向派生类对象

1.不能将基类对象赋值给派生类对象
2.不能将派生类的引用绑定到基类的对象
3.不能将派生类的指针指向基类的对象

总结:类型适应,派生类对象是可以适用于基类对象的。(重要)

五,多态

多态:多于同一种指令(警车鸣笛),针对不同的对象(普通人,警察,嫌疑犯),产生不一样的行为(正常行为,抓捕,藏起来)

分类

静态多态:函数重载,运算符重载 ,模板都是属于静态多态。发生的时机在编译的时候
add(int,int)
add(float,float,float)
add(3,4) add(3,4,5)
动态多态:发生的时机在运行的时候。使用虚函数进行体现。

六,虚函数

定义

成员函数的前面加上virtual关键字的函数,称为虚函数

重定义要求

1.基类与派生类的函数名字要相同
2.函数的参数列表也要相同(包括参数的个数,参数的类型,参数的顺序)
3.函数的返回类型也要一致

总结:基类与派生类中的同名函数,除了函数体可以不一样之外,其他的全部都要保持一致。(函数的名字,函数的返回类型,函数的参数列表(参数个数,参数的顺序,参数类型))

tips:虚表仅有一张,可以通过虚表的指针偏移进行访问其它虚函数请添加图片描述

动态多态被激活的五个条件(重要)

1.基类要定义虚函数
2.派生类要重写(重定义,覆盖)该虚函数
3.创建派生类的对象
4.基类的指针指向派生类的对象
5.基类的指针调用虚函数

哪些函数不能被设置为虚函数

  1. 普通函数(非成员函数):定义虚函数的主要目的是为了重写达到多态,所以普通函数声明为虚函数没有意义,因此编译器在编译时就绑定了它。(因为虚函数必须是成员函数,而普通函数是非成员函数)
  2. 静态成员函数:静态成员函数对于每个类都只有一份代码,所有对象都可以共享这份代码,他不归某一个对象所有,所以它也没有动态绑定的必要。(静态函数发生在编译时,虚函数体现多态发生在运行时)静态成员函数没有this指针,是被该类的多个对象共享的,就是唯一的
  3. 内联成员函数:内联函数本就是为了减少函数调用的代价,所以在代码中直接展开。但虚函数一定要创建虚函数表,这两者不可能统一。另外,内联函数在编译时被展开,而虚函数在运行时才动态绑定。内联函数如果写成虚函数,那么就是去了内联的函数
  4. 构造函数:构造函数发生的时机在编译的时候,而虚函数要体现多态,必须在运行的时候;构造函数是不可以被继承的,而虚函数时可以被继承的;如果将构造函数设置为虚函数,那么就需要通过虚表找到虚函数的入口地址,那么就需要虚函数指针指向虚表,而虚函数指针存在对象布局的最前面,而如果构造函数不调用,那么对象就不一定是完整的,那么对象的存储布局的前面就不一定有虚函数指针,那如果没有虚函数指针就不能指向虚表。 (这个原因很简单,主要从语义上考虑。因为构造函数本来是为了初始化对象成员才产生的,然而虚函数的目的是为了在完全不了解细节的情况下也能正确处理对象,两者根本不能“ 好好相处 ”。因为虚函数要对不同类型的对象产生不同的动作,如果将构造函数定义成虚函数,那么对象都没有产生,怎么完成想要的动作呢)
  5. 友元函数:如果友元函数本身是一个普通函数,那么友元函数不能被设置为虚函数;但是如果友元函数本身是成员函数,那么该友元函数是可以被设置为虚函数

虚函数的访问

1.使用指针进行访问
可以体现动态多态
2.使用引用进行访问
可以体现动态多态
3.使用对象进行访问
虚函数体现的就是普通成员函数的特性,在编译的时候就已经确定了函数调用
4.使用其他普通成员函数进行访问
5.使用特殊成员函数进行访问
在调用Father的构造函数的时候,调用func1()的时候,派生类Son的对象还没有构建完成,所以就看不到虚表这套逻辑,所以只能看到的func1()就是Father自己的。而当派生了Son销毁的时候,虚表都已经销毁了,所以再调用father的func2()的时候,已经看不到Son的这套逻辑,所以就只会调用到Father自己的func2函数,所以都没有体现动态多态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值