1. 从存储空间角度,虚函数对应一个指向vtable虚函数表的指针,这大家都知道,可是这个指向vtable的指针其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数。
  2. 从使用角度,虚函数主要用于在信息不全的情况下,能使重载的函数得到对应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。虚函数的作用在于通过父类的指针或者引用来调用它的时候能够变成调用子类的那个成员函数。而构造函数是在创建对象时自动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。
  3. 构造函数不需要是虚函数,也不允许是虚函数,因为创建一个对象时我们总是要明确指定对象的类型,尽管我们可能通过实验室的基类的指针或引用去访问它但析构却不一定,我们往往通过基类的指针来销毁对象。这时候如果析构函数不是虚函数,就不能正确识别对象类型从而不能正确调用析构函数。
  4. 从实现上看,vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数从实际含义上看,在调用构造函数时还不能确定对象的真实类型(因为子类会调父类的构造函数);而且构造函数的作用是提供初始化,在对象生命期只执行一次,不是对象的动态行为,也没有必要成为虚函数。
  5. 当一个构造函数被调用时,它做的首要的事情之一是初始化它的VPTR。因此,它只能知道它是“当前”类的,而完全忽视这个对象后面是否还有继承者。当编译器为这个构造函数产生代码时,它是为这个类的构造函数产生代码——既不是为基类,也不是为它的派生类(因为类不知道谁继承它)。所以它使用的VPTR必须是对于这个类的VTABLE。而且,只要它是最后的构造函数调用,那么在这个对象的生命期内,VPTR将保持被初始化为指向这个VTABLE, 但如果接着还有一个更晚派生的构造函数被调用,这个构造函数又将设置VPTR指向它的 VTABLE,等.直到最后的构造函数结束。VPTR的状态是由被最后调用的构造函数确定的。这就是为什么构造函数调用是从基类到更加派生类顺序的另一个理由。但是,当这一系列构造函数调用正发生时,每个构造函数都已经设置VPTR指向它自己的VTABLE。如果函数调用使用虚机制,它将只产生通过它自己的VTABLE的调用,而不是最后的VTABLE(所有构造函数被调用后才会有最后的VTABLE)。

构造函数为什么不能是虚函数 ( 转载自C/C++程序员之家)的更多相关文章

  1. C++构造函数和析构函数调用虚函数时都不会使用动态联编

    先看一个例子: #include <iostream> using namespace std; class A{ public: A() { show(); } virtual void ...

  2. 构造函数为什么不能为虚函数 &amp; 基类的析构函数为什么要为虚函数

    一.构造函数为什么不能为虚函数 1. 从存储空间角度,虚函数相应一个指向vtable虚函数表的指针,这大家都知道,但是这个指向vtable的指针事实上是存储在对象的内存空间的.问题出来了,假设构造函数 ...

  3. 转 C++构造函数、析构函数、虚函数之间的关系

    C++构造函数.析构函数.虚函数之间的关系 1. 如果我们定义了一个构造函数,编译器就不会再为我们生成默认构造函数了.2. 编译器生成的析构函数是非虚的,除非是一个子类,其父类有个虚析构,此时的函数虚 ...

  4. C++构造函数中不能调用虚函数

    在构造函数中调用虚函数,并不会产生多态的效果,就跟普通函数一样. c++ primer 第四版中497页15.4.5构造函数和析构中的虚函数讲到,如果在构造函数或析构函数中调用虚函数,则运行的是为构造 ...

  5. C++析构函数定义为虚函数(转载)

    转载:http://blog.csdn.net/alane1986/article/details/6902233 析构函数执行时先调用派生类的析构函数,其次才调用基类的析构函数.如果析构函数不是虚函 ...

  6. C++ 构造函数或析构函数调用虚函数

    构造函数和析构函数中的虚函数 在执行基类构造函数时,对象的派生类部分是未初始化的.实际上,此时对象还不是一个派生类对象. 为 了适应这种不完整,编译器将对象的类型视为在构造或析构期间发生了变化.在基类 ...

  7. C++的构造函数为何不能为虚函数

    1. 存储空间角度:虚函数对应一个vtable,vtable存储于对象的内存空间 若构造函数是虚的,则需要通过 vtable来调用,若对象还未实例化,即内存空间还没有,无法找到vtable 2. 使用 ...

  8. C++ 构造函数、析构函数与虚函数的关系

    编译环境:windows 10 + VS2105 1.构造函数不能为虚函数 虚函数的作用是为了实现C++多态机制.基类定义虚函数,子类可以重写该虚函数.当子类重写父类虚函数后,父类指针指向子类地址时, ...

  9. C++转换构造函数和隐式转换函数 ~ 转载

    原文地址: C++转换构造函数和隐式转换函数 用转换构造函数可以将一个指定类型的数据转换为类的对象.但是不能反过来将一个类的对象转换为一个其他类型的数据(例如将一个Complex类对象转换成doubl ...

随机推荐

  1. ecshop在线手册前言及程序结构

    该在线手册是有模版堂转载而来:仅供参考 一.前言 为什么我们ecshop模板堂要重制ecshop在线手册呢?因为目前网上的一些教程有些是比较老的,有些是不全面的,官方的手册也已经很久没有更 新,很多刚 ...

  2. Sqlite数据库简介

    在应用sqlite之前需要添加sqlite库,那么我们就会发现有3和3.0的区别,开始我也并不懂,后才知道: 实际上libsqlite3.dylib本身是个链接,它指向libsqlite3.0.dyl ...

  3. 软件测试之WEB测试经典总结

    在Web工程过程中,基于Web系统的测试.确认和验收是一项重要而富有挑战性的工作.基于Web的系统测试与传统的软件测试不同,它不但需要检查和验证是否按照设计的要求运行,而且还要测试系统在不同用户的浏览 ...

  4. 火狐对innerHtml的支持问题

    最新的Firefox是支持innerHTML的,但是不支持innerText.解决办法是将innerText换成textContent. $.getJSON("/api/Articles&q ...

  5. 关于cshtml中的js对动态编译支持的问题

    问题:MVC4中支持对ViewBag.ViewDate等的动态编译,但是在js中对它的支持就是有问题.虽然是可以动态编译,但是动态编译之后,断点无法获取. $.getJSON("/api/A ...

  6. break和continue语句

    跳转语句中断当前的执行过程,C++语言提供了4中跳转语句:break.continue.goto和return. break语句 break语句负责终止离他最近的while.do while.for或 ...

  7. php动态调用方法_sux

    <form  action=""> <input type="hidden" name="mod" id="mo ...

  8. C#_dropdownlist_1

    关于ASP.net MVC 中DropDownList绑定与提交数据   在做 ASP.net MVC项目中,数据绑定也是很关键的,现在以个人经验与大家交流下 ASP.net MVC 中DropDow ...

  9. iOS 开发中你是否遇到这些经验问题(二)

    前言: 1.在Block中一起使用weakSelf与strongSelf的含义 我们都会声明一个弱引用在block中使用, 目的就是防止循环引用, 那么weakSelf与strongSelf一起使用目 ...

  10. Web页面向后台提交数据的方式和选择

    1.通过表单提交 这是HTML支持最传统的提交方法,需要创建表单,然后表单包含各种类型的表单元素,还要有一个提交按钮,通过提交按钮来提交到后台,这种方式提交后页面会刷新. 2.通过网页链接提交 可以在 ...