今天看了一道迅雷的笔试题目,然后引起一段思考,题目如下:

下列关于虚函数的说法正确的是()
A、在构造函数中调用类自己的虚函数,虚函数的动态绑定机制还会生效。
B、在析构函数中调用类自己的虚函数,虚函数的动态绑定机制还会生效。
C、静态函数不可以是虚函数
D、虚函数可以声明为inline

此题答案给的是BCD,当时我就产生很大疑惑,所以我对四个选项依依来验证。

1、首先对于AB选项,我做了如下代码:

 #include <iostream>
using namespace std;
class ClassA
{
public:
ClassA()
{
cout<<"classA-begin"<<endl;
OutPut();
cout<<"classA-endl"<<endl;
}
virtual ~ClassA()
{
cout<<"~classA-begin"<<endl;
OutPut();
cout<<"~classA-endl"<<endl;
}
void virtual OutPut()
{
cout<<"A"<<endl;
}
}; class ClassB:public ClassA
{
public:
ClassB()
{
cout<<"ClassB-begin"<<endl;
OutPut();
cout<<"ClassB-endl"<<endl;
}
virtual ~ClassB()
{
cout<<"~ClassB-begin"<<endl;
OutPut();
cout<<"~ClassB-endl"<<endl;
}
void OutPut()
{
cout<<"B"<<endl;
} }; int main()
{
ClassA *a=new ClassB();
a->OutPut();
delete a;
getchar();
return ; }

在vs2010中输出结果为:

可以看到,在new ClassB时,虽然在父类ClassA的构造函数调了的是被ClassB覆盖的虚函数Output(),但是实际上还是调用的ClassA的OutPut。这是因为

继承类在构造的时候总是首先调用其基类的构造函数来对属于其基类的部分进行构造,在这个时候,整个类被当作基类来处理,继承类的部分对整个类来说好像不存在一样,直到基类的构造函数退出并进入继承类的构造函数,该类才被当作继承类来出来处理。对析构也一样,只是析构的顺序正好相反。

由此可知AB错误。(可以参考:http://www.cnblogs.com/xiaoxibo/archive/2011/07/18/2212612.html

对于C选项:

因为静态成员函数没有this,也就没有存放vptr的地方,同时其函数的指针存放也不同于一般的成员函数,其无法成为一个对象的虚函数的指针以实现由此带来的动态机制。静态是编译时期就必须确定的,虚函数是运行时期确定的。故C项正确。

对于D选项:

inline函数和virtual函数有着本质的区别,inline函数是在程序被编译时就展开,在函数调用处用整个函数体去替换,而virtual函数是在运行期才能够确定如何去调用的,因而inline函数体现的是一种编译期机制,virtual函数体现的是一种运行期机制。
因此,内联函数是个静态行为,而虚函数是个动态行为,他们之间是有矛盾的。
函数的inline属性是在编译时确定的, 然而,virtual的性质则是在运行时确定的,这两个不能同时存在,只能有一个选择,文件中声明inline关键字只是对编译器的建议,编译器是否采纳是编译器的事情。
我并不否认虚函数也同样可以用inline来修饰,但你必须使用对象来调用,因为对象是没有所谓多态的,多态只面向行为或者方法,但是C++编译器,无法保证一个内联的虚函数只会被对象调用,所以一般来说,编译器将会忽略掉所有的虚函数的内联属性。

所以D正确。

故此题答案为CD

c++有关构造函数和析构函数中调用虚函数问题的更多相关文章

  1. 【校招面试 之 C/C++】第10题 C++不在构造函数和析构函数中调用虚函数

    1.不要在构造函数中调用虚函数的原因 在概念上,构造函数的工作是为对象进行初始化.在构造函数完成之前,被构造的对象被认为“未完全生成”.当创建某个派生类的对象时,如果在它的基类的构造函数中调用虚函数, ...

  2. 在构造函数和析构函数中调用虚函数------新标准c++程序设计

    在构造函数和析构函数中调用虚函数不是多态,因为编译时即可确定调用的是哪个函数.如果本类有该函数,调用的就是本类的函数:如果本类没有,调用的就是直接基类的函数:如果基类没有,调用的就是间接基类的函数,以 ...

  3. 读书笔记 effective c++ Item 9 绝不要在构造函数或者析构函数中调用虚函数

    关于构造函数的一个违反直觉的行为 我会以重复标题开始:你不应该在构造或者析构的过程中调用虚函数,因为这些调用的结果会和你想的不一样.如果你同时是一个java或者c#程序员,那么请着重注意这个条款,因为 ...

  4. EC笔记,第二部分:9.不在构造、析构函数中调用虚函数

    9.不在构造.析构函数中调用虚函数 1.在构造函数和析构函数中调用虚函数会产生什么结果呢? #; } 上述程序会产生什么样的输出呢? 你一定会以为会输出: cls2 make cls2 delete ...

  5. C++箴言:避免构造或析构函数中调用虚函数

    如果你已经从另外一种语言如C#或者Java转向了C++,你会觉得,避免在类的构造函数或者析构函数中调用虚函数这一原则有点违背直觉.但是在C++中,违反这个原则会给你带来难以预料的后果和无尽的烦恼. 正 ...

  6. C++进阶--构造函数和析构函数中的虚函数

    //############################################################################ /* 任何时候都不要在构造函数或析构函数中 ...

  7. 【C++】不要在构造函数或析构函数内调用虚函数

    这个问题来自于<Effective C++>条款9:永远不要在构造函数或析构函数中调用虚函数 . 假设有如下代码: class Transaction {// 所有交易的基类 public ...

  8. C++构造与析构函数中调用虚函数的问题

    前些天想把以前写的内存池算法重写一遍,跨平台是第一目标,当时突发奇想,因为不愿意做成一大堆#if..#end,所以想利用C++的多态性,但是怎么让内存池完好退出却没想到自认为完美的方案.但是一个很偶然 ...

  9. C++-不要在构造和析构函数中调用虚函数

    在实习的单位搞CxImage库时不知为什么在Debug时没有问题,但是Release版里竟然跳出个Pure virtual function call error! 啥东西呀,竟然遇上了,就探个究竟吧 ...

随机推荐

  1. Swift学习笔记(4):字符串

    目录: 初始化 常用方法或属性 字符串索引 初始化 创建一个空字符串作为初始值: var emptyString = "" // 空字符串字面量 var anotherEmptyS ...

  2. 18个你可能不相信是用CSS制作出来的东西

    与流行的看法相反,CSS不仅仅是用来提供一个WEB页面的基本风格,以使它看起来更有吸引力.还有很多其他的事情,CSS也可以做的很好.由于它创建动画和交互的能力,CSS集合HTML以及JavaScrip ...

  3. Ubuntu设置终端相对短路径

    这个设置相对实际上是比较简单的.在自己的家目录打开.bashrc 找到PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$' 只需要将w修改为大写W保存, ...

  4. C#设置richtextbox某一段文本颜色

    假设 RichTextBox1 文本是"你好,我爱你中国",想要把中国变为红色,则 可以先找到中的位置是 7 :国的位置是8 设置 RichTextBox1.SelectionSt ...

  5. Java 多线程详解(一)------概念的引入

    这是讲解 Java 多线程的第一章,我们在进入讲解之前,需要对以下几个概念有所了解. 1.并发和并行 并行:指两个或多个时间在同一时刻发生(同时发生): 并发:指两个或多个事件在一个时间段内发生. 在 ...

  6. java虚拟机学习-慢慢琢磨JVM(2)

    1 JVM简介 JVM是我们Javaer的最基本功底了,刚开始学Java的时候,一般都是从“Hello World”开始的,然后会写个复杂点class,然后再找一些开源框架,比如Spring,Hibe ...

  7. cas4.2.7实现单点登录

    准备前参考: cas server下载地址 cas client 下载地址 安全cookie setSecure详解 Spring通过构造方法注入的四种方式 cas 学习博文 自定义登录页和登录认证 ...

  8. [转]tomcat部署

    转载博客原文地址:  http://www.cnblogs.com/xing901022/p/4463896.html 阅读目录 介绍 静态部署——在tomcat启动时部署 动态部署——在tomcat ...

  9. htm语言的语法基础及规则

    HTML的主要语法是元素和标签.元素是符合DTD(文档类型定义)的文档组成部分,如title(文档标题).IMG(图象).table(表格)等等.元素名不区分大小写的.HTML用标签来规定元素的属性和 ...

  10. NodeMCU入门(5):Docker Image 构建固件,开启SmartConfig

    准备工作 1.NodeMCU模块 2.ESP8266Flasher.exe 3.EspTouch.apk 3.docker toolbox(win7系统) 或 docker(win10以上),本教程是 ...