大家好
欢迎回来继续学习
C++语言程序设计
这一节呢
我们来学习类型转换
现在我们要学的类型转换呢
是基类与派生类之间的
那么我们来看看
基类与派生类
这两个有密切关联的类之间
有没有一些
必然的可转换规律呢
当然是有的
首先
我们本能地想到
既然派生类
全盘照收了基类的内容
全都继承过来了
那是不是一个派生类的对象
就可以当基类对象用呢
公有继承的情况下
确定是这样的
公有派生类的对象
它是可以被当做基类对象使用的
但是反过来是不行的
为什么呢
因为经过派生以后
派生类的东西
比基类里面的东西多
但是基类里面原有的内容
经过公有派生
就都拿到派生类中来了
而且公有派生
使得基类的对外访问接口
是保持不变的
所以呢
派生类对象
它可以隐含转换为基类的对象
派生类的对象
可以初始化基类的引用
派生类的指针
可以隐含转换为基类的指针
那
但是呢
这样经过转换以后
通过基类的对象名 指针
就只能使用从基类
继承的成员
派生类新增的成员
那就不能使用了
现在我们来看一个例子
这个例子很有意思
我们想利用这个类型转换规则
编写一个非常通用的显示函数
那么我们这个希望
它特别通用的这种
这种这种很好的愿望
能实现吗
拭目以待
在这里我们定义了Base1
作为基类
然后定义Base2
以公有方式继承了Base1
然后Derived再次继承Base2
也是公有方式
这样呢
就是Base1派生出Base2
Base2又派生出Derived
每个类都有一个
同名的display函数
但是呢
函数体执行的功能各不相同
我们用输出一行
不同的字符串来模拟
它的功能各不相同
接下来呢我们希望
能够写一个通用的显示函数fun
我们知道
如果这个参数类型是基类的指针
那么实参就可以是什么
是派生类的地址
我们知道用派生类的地址
是可以初始化
公有基类的指针的
所以我们期望用这个指针
在运行时
根据需要指向不同的派生对象
然后调用display函数
希望它能够调用到
各个派生类对象
自己的display函数
看看事实是不是这样呢
现在我们通过单步运行
看一下 观察一下这个情况
现在我们通过调试方式
单步跟踪运行进来
在主函数中呢
看到我们构造了这个
Base1的对象
Base2的对象
和Derived对象然后第一次调用fun函数的时候
将Base1的地址传过去
那进到这里面了
我们这个ptr
指向的是Base1的对象
然后看它调用哪个函数去了
进到display函数里面
再进到
Base1的display函数里面了
好 执行完了回来
接下来呢
给它再传一个Base2的对象
地址Base2对象地址
现在把它传进去
现在我们知道
这个指针
虽然它是Base1类型的指针
但是它指向的对象
是Base2类型的了
调用谁的display函数呢
跟踪进去
它还是调用了
Base1的display函数
这个没有达到
我们希望的这个理想状态
再观察一次
当将Derived地址给它的时候
走到哪儿去了
进到fun函数里面
这个ptr呢得到了Derived地址
指向的是Derived的对象
结果呢
它还是进到
Base1的display函数里面了
所以完全没有达到
我们期望的这个效果
没有达到这个期望的效果
那么看一下运行结果呢
确实都是调用的
Base1的display函数
运行结果
刚才看的是这个样子
所以没有达到这个效果
但是呢
我们看到这个程序以后
我们会期望这个效果
这种直接的期望
跟得到的结果不一样
使得程序的可读性很不好
所以在这儿建议大家
不要重新定义
继承而来的非虚函数
什么是非虚函数呢
虚函数我们还没有学
第八章讲虚函数
那当然现在的函数
这些display都不是虚函数
那么我们必要重新
用同样的名字去定义
因为我们这样的话就期望
它指针指向各自对象的时候
表现的不一样
但是达不到这个期望
那是不是我们这个期望
就一定达不到呢
是达得到的
只要我们用虚函数
就可以解决这个问题了
这个问题呢
我们先留着
第八章就会解决的