如何确定C++继承层次中的函数调用
```cpp //============================================================================
// Name : TS.cpp
// Author : jiudianren
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================ #include <iostream>
#include <functional> using namespace std; class A
{
protected:
int m_data;
public:
A(int data = )
{
m_data = data;
}
int GetData()
{
return doGetData();
}
virtual int doGetData()
{
return m_data;
}
}; class B: public A
{
protected:
int m_data;
public:
B(int data = )
{
m_data = data;
}
int doGetData()
{
return m_data;
}
}; class C: public B
{
protected:
int m_data;
public:
C(int data = )
{
m_data = data;
} int doGetData()
{
return m_data;
}
}; void ref(C* & d)
{
cout<<d->GetData()<<endl; //题1
cout<<d->A::GetData()<<endl; //题2
cout<<d->B::GetData()<<endl; //题3
cout<<d->C::GetData()<<endl; //题4 cout<<d->doGetData()<<endl; //题5
cout<<d->A::doGetData()<<endl; //题6
cout<<d->B::doGetData()<<endl; //题7
cout<<d->C::doGetData()<<endl; //题8
}
int main()
{
C c();
cout<<c.GetData()<<endl; //题1
cout<<c.A::GetData()<<endl; //题2
cout<<c.B::GetData()<<endl; //题3
cout<<c.C::GetData()<<endl; //题4 cout<<c.doGetData()<<endl; //题5
cout<<c.A::doGetData()<<endl; //题6
cout<<c.B::doGetData()<<endl; //题7
cout<<c.C::doGetData()<<endl; //题8 cout<<"sssssssssss"<<endl; //题8
C *f=new C();
C *d=f;
cout<<d->GetData()<<endl; //题1
cout<<d->A::GetData()<<endl; //题2
cout<<d->B::GetData()<<endl; //题3
cout<<d->C::GetData()<<endl; //题4 cout<<d->doGetData()<<endl; //题5
cout<<d->A::doGetData()<<endl; //题6
cout<<d->B::doGetData()<<endl; //题7
cout<<d->C::doGetData()<<endl; //题8 cout<<"sssssssssss"<<endl; //题8
ref(f);
return ;
} ```
理解C++中继承层次的关键在于理解如何确定函数调用。确定函数调用遵循以下四个步骤:
(1) 首先确定进行函数调用的对象、引用或指针的静态类型。
(2) 在该类中查找函数,如果找不到,就在直接基类中查找,如此循着类的继承链往上找,直到找到该函数或者查找完最后一个类。如果不能在类或其相关类中找到该名字,则调用是错误的。
(3) 一旦找到了该名字,就进行常规类型检查,查看该函数调用是否合法。
(4) <i>若函数调用合法,编译器就生成代码。如果函数是虚函数且通过引用或指针调用,则编译器生成代码以确定根据对象的动态类型运行哪个函数版本,否则,编译器生成代码直接调用函数。
<ii>若函数调用不合法,则调用是错误的,且不再像(2)一样循着继承链往上找。
题1----题8
构造函数从最上层的基类开始构造,各个类的同名变量没有形成覆盖,都是单独的变量。
题1:
静态类型为C类,故在C类中找GetData()函数,C类中没有GetData()函数,由步骤(2),在其直接基类B类中查找,B类中也没有,再在A类中找,在A类中找到,且常规类型检查无误,调用合法,运行之。在其函数体类调用的doGetData()是虚函数,但不是通过引用或指针调用,故没有动态绑定,则由静态类型决定调用哪一个版本的doGetData(),静态类型为C类,C类中没有doGetData(),在其基类B类中找,找到,运行之,返回的是B::m_data,其值为默认实参值1。故本行输出1。
其他题类似,答案为1,1,1,1,1,0,1,1。
如何确定C++继承层次中的函数调用的更多相关文章
- c++ 容器、继承层次、句柄类
一.容器与继承 在容器中保存有继承关系的对象,如果定义成保存基类对象,则派生类将被切割,如果定义成保存派生类对象,则保存基类对象又成问题(基类对象将被强制转换成派生类对象,而派生类中定义的成员未被初始 ...
- Entity Framework 6 Recipes 2nd Edition(10-6)译 -> TPT继承模型中使用存储过程
10-6. TPT继承模型中使用存储过程 问题 想在一个TPT继承模型中使用存储过程 解决方案 假设已有如Figure 10-6所示模型. 在模型里, Magazine(杂志) and DVD继承于基 ...
- Entity Framework 6 Recipes 2nd Edition(10-7)译 -> TPH继承模型中使用存储过程
10-7. TPH继承模型中使用存储过程 问题 用一个存储过程来填充TPH继承模型的实体 解决方案 假设已有如Figure 10-7所示模型. 我们有两个派生实体: Instructor(教员)和St ...
- 《Entity Framework 6 Recipes》中文翻译系列 (35) ------ 第六章 继承与建模高级应用之TPH继承映射中使用复合条件
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-11 TPH继承映射中使用复合条件 问题 你想使用TPH为一张表建模,建模中使 ...
- java继承关系中成员变量,构造方法,成员方法的关系
Java继承中的成员关系 A:成员变量 a:子类的成员变量名称和父类中的成员变量名称不一样,这个太简单写那个名字就访问那个名字! b:子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢? 子 ...
- C++中构造函数调用构造函数
今天想做道矩阵的题目时,却卡在一些编程细节上了,找了好久才发现原来是在构造函数处出了问题,然后上网百度了下,发现这篇文章说得很好:从一道题谈C++中构造函数调用构造函数,很棒! 还补充一点: 看来自己 ...
- JavaSE复习日记 : 继承关系和super关键字以及继承关系中方法的覆写
/* * 类的继承和super关键字 * * 软件开发的三大目的: * 可拓展性; * 可维护性; * 可重用性; * * 这里单说下可重用性这一项: * 为了代码复用,复用方式有: * 函数的调用复 ...
- [SignalR]在非Hub继承类中使用脚本方法
原文:[SignalR]在非Hub继承类中使用脚本方法 新建一个普通类OutHub,里面包含一个脚本方法OutHubTest. 因为大家知道,若能让脚本调用到的话,必须继承Hub,那怎么实现了?通过G ...
- C#继承关系中【方发表】的创建和调用
—C#继承关系中[方发表]的创建和调用 Insus.NET实现一个最炫最原创的验证码.你可以从下面的一步一步的演译. 实现一个验证码,需要了解的是,它最基本是随机产生字符串:<在ASP.NET ...
随机推荐
- .NET 文件上传和文件接收
有时候,我们需要在后台端发起向指定的“文件接收接口”的文件传输请求,可以采用HttpWebRequest方式实现文件传输请求. 1.HttpWebRequest文件传输请求的代码如下: 其中,url为 ...
- spring boot使用WebClient调用其他系统提供的HTTP服务
WebClient的请求模式属于异步非阻塞,能够以少量固定的线程处理高并发的HTTP请求 WebClient是Spring WebFlux模块提供的一个非阻塞的基于响应式编程的进行Http请求的客户端 ...
- python基础教程_查询价格
少儿编程和数学是有这一定联系的,若是将编程弄好了,数学成绩也就会有所提高,今天就为大家来介绍一下一个关于数学的相关编程,现在我们就来看看吧! 题目描述 编程实现以下功能:查询水果的单价.有4种水果,苹 ...
- Django-11-Form组件
1. 概述 Django的Form组件一般功能有: 验证用户输入 生成html代码 返回错误信息 创建Form类 from django.shortcuts import render, redire ...
- Python输出菱形
最近准备熟悉下Python的基础语法,准备练习下输出菱形.刚好作为自己blog的开篇~~ n =10 #控制菱形的大小 for i in range(1, n): for j in range(int ...
- 【转】Isim——基本技巧
来源:电子产品世界: 注:本文由NingHeChuan本人多出整理所得,原文章图片不清晰,自己整理配图后重新发表 安装好ISE,系统已经自带了ISim仿真软件,相比于专业的仿真软件Modelsim,I ...
- 华为云·寻找黑马程序员#【代码重构之路】如何“消除”if/else【华为云技术分享】
1. 背景 if/else是高级编程语言中最基础的功能,虽然 if/else 是必须的,但滥用 if/else,特别是各种大量的if/else嵌套,会对代码的可读性.可维护性造成很大伤害,对于阅读代码 ...
- 向Spring 容器中注入对象的几种方法
1.使用@Bean 注解,用于注入第三方 jar 包到SpringIOC容器中. 2.使用 @Import({Order.class, Member.class, MyImportBeanDefini ...
- java之mybatis之字段映射及多对一
1. 数据库中表的列名和实体类的属性名称不一致. 可以使用 resultMap来解决. <select id="findAll" resultMap="UserMa ...
- 2019 蚂蚁金服java面试笔试题 (含面试题解析)
本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.蚂蚁金服等公司offer,岗位是Java后端开发,因为发展原因最终选择去了蚂蚁金服,入职一年时间了,也成为了面 ...