当前位置: 首页 > news >正文

C++_继承与多态双双环绕,正确理解“派生类怎么‘继承’基类的成员函数”(1/2)

先来看一道经典的面试题:

以下程序输出结果是什么()
A: A->0   B: B->1   C: A->1   D: B->0   E: 编译出错   F: 以上都不正确

class A
{
public:virtual void func(int val = 1) { std::cout << "A->" << val << std::endl; }virtual void test() { func(); }
};
class B : public A
{
public:void func(int val = 0) { std::cout << "B->" << val << std::endl; }
};
int main(int argc, char* argv[])
{B* p = new B;p->test();return 0;
}

你的心里是否有答案,以及每一步调用如何如何


铺垫知识

C++里,我们知道派生类初始化时,其对象首先会“安插”一个基类对象(安插:首先调用基类构造函数,完成基类对象初始化);然后接着完成本类新增成员变量的初始化,于是一个派生类对象长这样:

图1 一个派生类对象占的内存里有些什么

可以在这里看到,并没有“基类的成员函数”啊?那为什么还说派生类还继承了基类的成员函数,这“继承”怎么个继承法?

因此,对「普通成员函数」(非 virtual、非 static)来说,「继承」并不是在派生类里再写一份代码,而是让编译器在派生类的作用域里自动拥有了「对基类那些函数的调用权」

具体理解:

图2:具体理解结合代码

上文提到:派生类继承了基类的成员函数,实际上是获得了其对基类那些函数的调用权。所以此处p虽然指向b,但是它依然可以去调用test() ——尽管B类没有test()定义。

接下来是关键,怎么找到 test()的?

b在B::里没找到test()定义,于是自然顺着继承树里查到A::了。进入A::test()后,this 的静态类型自然是A*,但这步转换是完全合法且安全的(向上转型—— B* —> A*)。

如果要理解:那就是进入了基类的地界,就自然而然向上转型。

// p->test()就等价于
A::test(p);   // 把 p 转成 A* 作为 this 传入(此处把隐含的this指针挑明了,为了好理解)

所以:派生类对象虽然获得了基类成员函数的调用权,但这真正调用到基类的成员函数时,隐含的this*指针已经安全向上转型


如今加入了“多态”这一语境:

多态构成条件
1. 基类指针或者引用调用

2. 调用虚函数

再看

p->test();// p为B* ,并非基类指针调用;两个条件不足其一,即不构成多态

而当进入了A::test()时,p向上转型成了A*:

图3 this已经是基类指针

此时满足了基类指针调用(多态条件一),亦满足了调用了虚函数func()(多态条件二)—— 编译器此时不会像刚刚一样“ 直接生成一条普通call指令”;而是去根据p真正指向的对象b里,存着的虚表_vfptr中func这个虚函数的地址,生成调用指令。

图4 调用到了b重写的虚函数func()

那答案就是:“B->0”了?我们暂先按下不表。先来总结“继承和多态下,调用成员函数分析步骤

***继承和多态下,调用成员函数分析步骤***

1)如果第一句是Derive对象(指针)调用成员函数(忽略成员函数具体逻辑):

  • 如果成员函数在本类中并无定义,则顺着继承数往上去到基类作用域寻找——找到后进入下一步(此时完成this指针的向上转型)。
  • 如果成员函数在本类有直接定义,找到后进入下一步。

2)如果是基类指针或引用调用成员函数(忽略成员函数具体逻辑)

  • 成员函数是虚函数,则回到调用函数的指针真正指向的对象的虚表里取虚函数地址,找到真正执行的函数。找到了进入下一步。
  • 如果不是虚函数,那么就直接去基类作用域寻找函数定义——此时就不能往下(往派生类作用域寻找)

小总结:看是否满足多态,不满足就正常逻辑分析。


虚函数的重写:实际上是重写函数体(函数行为),而缺省参数不会被重写。

所以可以理解为本类的虚函数的定义为:基类的声明 + 重写的函数体

所以此处的val还是为1 ,最终答案为B. B->1.

http://www.dtcms.com/a/432613.html

相关文章:

  • 网站可以做软著吗网站制作品牌公司
  • 全球最热门网站网站建设推广方案策划书
  • 免费建站资源青岛网站建设官网
  • 策划的网站云南省建设厅网站发文
  • 网站内部优化策略中山网站建设seo优化营销制作设计
  • [实战]解决WSL2中TFTP服务无法被外部设备访问的问题
  • 青岛网站设计品牌企业怀化找工作网站
  • 一个网站做两种产品引航博景网站做的很好吗
  • 广州建站推广国内知名的app开发
  • 搜狗网站车机油哪个网站做的好
  • 网站建设 温州网站扫码怎么做
  • 网站建设的费用预算如何写野花影视大全在线西瓜
  • 西宁市城乡建设网站wordpress调取指定分类下的文章
  • 深圳专业网站公司做众筹网站
  • 龙岗网站建设深圳信科做平行进口的汽车网站
  • 手机网站微信代码百度学术论文查重入口
  • 台州网站公司那里好长沙招聘网最新招聘
  • 阿里云域名注册服务网站国内免费域名注册
  • 中国做网站公司泰州网站建设优化建站
  • 湛江网站制作优化wordpress模板下载
  • 学校门户网站建设的优势网站备案上海
  • 远程时代网站建设社交软件开发费用
  • 广州申请公司注册网站作文网下载
  • 网站建设技术支持祥云平台常见的网络营销推广方式有哪些
  • 变分推断:从优化视角逼近复杂后验分布的强大工具
  • 金融网站制作建设论坛网站步骤
  • 如何建立手机网站用wordpress做论坛好吗
  • 沙坪坝做网站网站建设企业建站哪家好
  • 免费个人网站下载网站更换运营商要重新备案
  • 网站友情链接模块介绍公司注册网上申请流程