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. ServletContext1

    ---------------ConfigServlet.java----------- protected void doGet(HttpServletRequest request, HttpSe ...

  2. [Java 7][msvcr100.dll] Error when load Eclipse

    [Problem] After I updated to Java 7, I could not load Eclipse. Here comes the erros: Eclipse: eclips ...

  3. 将某个组中的账户移动到新的OU下

    将某个组中的账户移动到新的OU下 #定义组名 $groupname = "testg" #定义新的OU名称 $newou = "OU=oo,OU=Admins,dc=dd ...

  4. Codeforces Round #200 (Div. 1)A. Rational Resistance 数学

    A. Rational Resistance Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/343 ...

  5. [Practical Git] Format commit history with git log arguments

    When running the git log command, we can pass in options as arguments toformat the data shown for ea ...

  6. POJ 1329 三角外接圆

    Circle Through Three Points Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3169   Acce ...

  7. Android仿腾讯应用宝 应用市场,下载界面, 有了进展button

    近期应用市场做,需要使用.下载与进度显示button,因此,要寻找其他大神做,直接用于改善.和很多无用的切出.在改进共享后. 再一次改变.当下载进度时,有进步.进度显示自己主动运行文本.并设置背景为灰 ...

  8. UVA - 10883 Supermean

    Description Problem F Supermean Time Limit: 2 second "I have not failed. I've just found 10,000 ...

  9. MySQL入门笔记

    MySQL入门笔记 版本选择: 5.x.20 以上版本比较稳定 一.MySQL的三种安装方式: 安装MySQL的方式常见的有三种: ·          rpm包形式 ·          通用二进制 ...

  10. c/c++指针基础使用

    #include <iostream> #include <string> using namespace std; int main() { "; "; ...