C++可见版本,他说,这本书是采访的主题,调查超载、盖、多态性等概念,比较有代表性的。今天上午,远程辅导 Yan Wang 学生们学习 Qt 时还觉得这个话题,假设你能正确地理解这一主题,注意对于 C++ 该函数重载、盖、虚函数、有了正确的认识和多态性。呢。再来学习 Qt 就顺风顺水了。

题目是酱紫的:

#include <iostream>
#include <string>
using namespace std;
class A
{
protected:
int m_data;
public:
A(int data = 0)
{
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 = 1)
{
m_data = data;
}
int doGetData()
{
return m_data;
}
};
class C : public B
{
protected:
int m_data;
public:
C(int data = 2)
{
m_data = data;
}
};
void main()
{
C c(10); cout << c.GetData() << endl;
cout << c.A::GetData()<< endl;
cout << c.B::GetData()<< endl;
cout << c.C::GetData()<< endl; cout << c.doGetData()<< endl;
cout << c.A::doGetData()<< endl;
cout << c.B::doGetData()<< endl;
cout << c.C::doGetData()<< endl;
}

程序执行后的输出结果是什么?

答案是:1 1 1 1 1 0 1 1

追问一下,去掉 A 类中 doGetData() 函数的 virtual 修饰,程序执行后的输出结果是什么?

答案是:0 0 0 0 1 0 1 1

说说我对这个题目的理解。

首先我们从对象的角度来看一下。
    先看 main() 函数中构造 c 对象的语句:

C c(10);

这句产生以下的效果:

  • c.m_data = 10;
  • ((B)c).m_data = 1;
  • ((A)c).m_data = 0;

为什么呢?

C c(10); 这行代码,定义了 c 对象。但实际上内存中有三个对象:

  1. class C 的实例对象,即 c
  2. 由于 C 是 B 的派生类,会产生一个 class B 实例对象,即 (B)c
  3. 由于 B 是 A 的派生类。会产生一个 A 实例对象,即 (A)c

每一个对象都有 m_data 成员变量, 依据继承关系,子类覆盖父类的同名成员(变量、函数)。 c 对象中实际上有三个同名的 m_data 变量。你通过不同的身份去看,会看到不同的 m_data 。

C 对象生成时。调用 B 、A 类的构造函数,对 B 、 A 初始化,结果就是:

  • c 对象的 m_data = 10;
  • ((B)c) 对象的 m_data = 1;
  • ((A)c) 对象的 m_data = 0.

这就是我们一開始给出的效果。

明确了对象的关系和 m_data 成员的值。咱们再来看 GetData() 函数。

GetData() 函数是 class A 的一个普通方法。依据继承关系, B 、 C 类都可以訪问 GetData() 方法,由于 B 、 C 没有重写 GetData() 。所以通过 B 、 C 的对象訪问 GetData() ,訪问的都是 A 的 GetData() 方法。

在 GetData() 中。调用了 doGetData() ,注意了,这是个虚函数!假设 A 的后裔重写了 doGetData() 函数,那么这里实际上会调用到继承关系上处于最底层的那个类的 doGetData() 函数,这就是虚函数和多态的概念。如你所见。 B 重写了 doGetData() 函数,所以当你调用 c.GetData() 。 B 的 doGetData() 会被调用, ((B)c).m_data 被返回。

事实上在 Qt 中,这样的使用方法比比皆是。

好啦。以下分析 main() 函数的输出结果。

doGetData() 带 virtual keyword

c.A::GetData() / c.GetData() / c.B::GetData() / c.C::GetData()

这些语句,都是调用 A::GetData() 。终于都调用 ((B)c).doGetData(), 就是B::doGetData() ,訪问的是 B 的对象,它的 m_data = 1 。所以 doGetData() 返回 1 。终于 GetData() 返回 1 。
   
    C 类未定义 doGetData() 函数,c.doGetData() 等同于 ((B)c).doGetData() , 訪问的是 B 的对象,它的 m_data = 1 。所以 c.doGetData() 结果是 1 。

c.A::doGetData() 。类域作用符限定了调用 A::doGetData()。訪问 A 的对象,返回 ((A)c).m_data = 0 。

c.B::doGetData() / c.C::doGetData() 终于都是訪问 B 对象的 doGetData() 方法, 返回都是 1 。

所以 doGetData() 带 virtual keyword,程序输出 1 1 1 1 1 0 1 1 。

去掉 doGetData() 的 virtual keyword

由于 GetData() 是 A 类的方法,而 doGetData() 不是虚函数。 A 类的 GetData() 内调用的 doGetData() 方法仅仅可能是 A 的对象的方法,((A)c).m_data = 0 ,所曾经四个cout结果都是 0 。

c.doGetData() ,C 的对象内没有实现这个函数,调用父类的,即 B 的对象的 doGetData() 方法。訪问的 m_data 是 ((B)c) 对象的,是 1 。

c.A::doGetData() ,调用 A 的方法。訪问 A 的对象 ((A)c).m_data ,结果是 0 。

c.B::doGetData() / c.C::doGetData() 。调用 B 的方法。訪问 B 的对象 ((B)c).m_data 。结果为 1 。

所以,终于结果是:0 0 0 0 1 0 1 1

我不知道说清楚没有什么?

版权声明:本文博客原创文章,博客,未经同意,不得转载。

详细说明C++笔试题,调查超载、盖、多态的更多相关文章

  1. C/C++ 笔试题

    /////转自http://blog.csdn.net/suxinpingtao51/article/details/8015147#userconsent# 微软亚洲技术中心的面试题!!! 1.进程 ...

  2. C/C++笔试题(很多)

    微软亚洲技术中心的面试题!!! .进程和线程的差别. 线程是指进程内的一个执行单元,也是进程内的可调度实体. 与进程的区别: (1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位 (2 ...

  3. 剑指Offer——京东实习笔试题汇总

    剑指Offer--京东实习笔试题汇总 编程题1 题目的详细信息已经记不住,只能大致描述一下,就是求最有价值的的委托信息. n.s.B.S其中n代表委托信息,s要求的最有价值的委托信息的个数,B代表买入 ...

  4. 【Android】一道Android OpenGL笔试题

    一道Android OpenGL笔试题 SkySeraph May. 5th 2016 Email:skyseraph00@163.com 更多精彩请直接访问SkySeraph个人站点:www.sky ...

  5. ThoughtWorks西邮暑期特训营 -- JavaScript在线笔试题

    ThoughtWorks 公司在西邮正式开办的只教女生前端开发的女子卓越实验室已经几个月过去了,这次计划于暑期在西邮内部开展面向所有性别所有专业的前端培训. 具体官方安排请戳:ThoughtWorks ...

  6. 收藏所用C#技术类面试、笔试题汇总

    技术类面试.笔试题汇总 注:标明*的问题属于选择性掌握的内容,能掌握更好,没掌握也没关系. 下面的参考解答只是帮助大家理解,不用背,面试题.笔试题千变万化,不要梦想着把题覆盖了,下面的题是供大家查漏补 ...

  7. 10道C++输出易错笔试题收集

    下面这些题目都是我之前准备笔试面试过程中积累的,大部分都是知名公司的笔试题,C++基础薄弱的很容易栽进去.我从中选了10道简单的题,C++初学者可以进来挑战下,C++大牛也可以作为娱乐玩下(比如下面的 ...

  8. 嵌入式Linux C笔试题积累(转)

    http://blog.csdn.net/h_armony/article/details/6764811 1.   嵌入式系统中断服务子程序(ISR) 中断是嵌入式系统中重要的组成部分,这导致了很 ...

  9. [NOIp 1998 提高组]Probelm 2 连接多位数【2011百度实习生笔试题】

    /*====================================================================== [NOIp 1998 提高组]Probelm 2 连接 ...

随机推荐

  1. WPF用SkewTransform画3D柱状图

    WPF用SkewTransform画3D柱状图 SkewTransform主要是对控件实现一种2-D扭曲,具体内容可以查看以下链接: http://msdn.microsoft.com/zh-cn/l ...

  2. 【Android接口实现】ActionBar利用整理的一些细节

    转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 关于ActionBar的使用,非常多大神早就已经写了非常好的文章进行了介绍,所以ActionBar的基本使用 ...

  3. Nginx 防CC攻击拒绝代理访问

    先大概说说简单的结构…前端一个Nginx反向代理,后端一个Nginx instance app for PHP…实际上就是个Discuz,之前面对CC攻击都是预警脚本或者走CDN,但是这次攻击者不再打 ...

  4. Oracle SQL Lesson (10) - 使用DDL语句创建和管理表

    数据库对象TableViewSequenceIndexSynonym 对象名称最长30个字符,不能与当前用户下其他对象重名.create table "select" as sel ...

  5. 【hadoop之翊】——基于CentOS的hadoop2.4.0伪分布安装配置

    今天总算是把hadoop2.4的整个开发环境弄好了,包括 windows7上eclipse连接hadoop,eclipse的配置和測试弄得烦躁的一逗比了~ 先上一张成功的图片,hadoop的伪分布式安 ...

  6. python 调用图灵机器人api实现简单的人机交互

    接入流程例如以下,须要先注冊开发人员帐号,之后会得到一个32位的key,保存下来,用于以后发送数据.http://www.tuling123.com/ 请求方式 演示样例: # -*- coding: ...

  7. linux 文件查看目录的数

    ls -l | grep '^-'| wc -l ls -l | grep -c '^-' ls -l 输出文件夹中的文件信息的一长串(注意,文件,不同于文件,它可能是一个文件夹.联系.设备文件) g ...

  8. redirect的错误用法asp.net怎么使用自定义错误

    工作了几年,写过程序也运营过网站,自定义错误也很熟悉了,最近再做项目发现有同事写了这样的代码 if (action != null) { id = Request.QueryString[" ...

  9. TabHost+RadioGroup搭建基础布局

    xml的形势如下: <tabhost> <linearlayout vertival> <framlayout weight=1/> <tabwidget g ...

  10. 文件翻译002片:Process Monitor帮助文档(Part 2)

    [筛选亮点] Process Monitor提供了一些方式来配置筛选器和高亮显示.         筛选器的包括与排除 您能够在筛选器中指定事件的属性,这样就能够令Process Monitor仅显示 ...