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. 完整的java字符串编码转换代码

    package book.String; import java.io.UnsupportedEncodingException; /** *//** * 转换字符串的编码 * @author joe ...

  2. Oracle学习(十四):管理用户安全性

    --用户(user) SQL> --创建一个名为 grace password是password 的用户,新用户没有不论什么权限 SQL> create user grace identi ...

  3. C# 如何获取某用户的“我的文档”的目录

    Console.WriteLine(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)); System.E ...

  4. HDU 1420 Prepared for New Acmer【中国剩余定理】

    /* 解决问题的思路:中国剩余定理,还要注意的是数据的类型,要使用__int64位 解决人:lingnichong 解决时间:2014-08-30 06:56:35 :简单题 */ Prepared ...

  5. 辛格尔顿和Android

    辛格尔顿(Singleton) .singleton.h,定义类的基本成员及接口 #ifndef SINGLETON_H_INCLUDE #define SINGLETON_H_INCLUDE cla ...

  6. 【原创】java中的父进程子进程 —— 坑爹的java Runtime.getRuntime().exec

    最近有一个需求,需要用一个java进程启动多个子进程来完成并发任务.由于必须给用户完成任务的反馈,所以需要父进程记录子进程的生命周期. exec方法返回一个Process对象,在当前进程内调用该对象的 ...

  7. ffmpeg架构和解码流程分析

    转 一,ffmpeg架构 1. 简介 FFmpeg是一个集录制.转换.音/视频编码解码功能为一体的完整的开源解决方案.FFmpeg的 开发是基于Linux操作系统,但是可以在大多数操作系统中编译和使用 ...

  8. CentOS7卸载KDE桌面(转)

    最初安装centos时选择了安装KDE桌面,打开很卡,没有用到,想卸载,可是试了网上的方法什么yum groupremove kde-desktop 都不奏效,于是只能自己找出KDE的包,然后yum卸 ...

  9. 好玩的WPF第二弹:电子表字体显示时间+多彩呼吸灯特效button

    我们先来看看Quartz MS字体动态显示系统时间的效果,难度相较于上一篇也要简单很多. 首先是定义一个TextBlock例如以下. <Grid> <TextBlock Name=& ...

  10. 我收集的sonar参考资料

    sonarQube代码质量管理工具环境筹建笔记 http://www.myexception.cn/open-source/1307345.html 配置sonar.jenkins进行持续审查 htt ...