zoukankan      html  css  js  c++  java
  • 【C++】深度探索C++对象模型读书笔记--构造函数语义学(The Semantics of constructors)(一)

    Default Constructor的构造操作

      对于class X,如果没有任何user-declared constructor, 那么会有一个default constructor被隐式(implicit)声明出来,一个被隐式声明出来的default constructor将是一个trivial consructor......

      下面讨论nontrivial default constructor的4种情况。

      1.带有Default Constructor的Member Class Object

        如果一个class没有任何constructor,但它内含有一个member object,而后者有default constructor,那么这个class的implicit default constructor就是“nontrivial”,编译器需要为该class合成出一个default constructor。不过这个合成操作只有在constructor真正被调用时才会发生。

         如果有多个class member objects都要求contructor初始化操作。C++语言要求以“member objects在class中的声明顺序“来调用各个constructors。这一点由编译器完成,它为每个constructor安插程序代码,以”member声明顺序“调用每一个member所关联的default constructors。这些代码将被安插在explicit user code之前。举个例子,假设我们有以下三个classes:

      

    class Dopey {public: Dopey();...};
    class Sneezy {public: Sneezy(int); Sneezy();...};
    class Bashful {public: Bashful();...};
    
    以及一个class Snow_White:
    class Snow_White {
    public:
        Dopey dopey; 
        Sneezy sneezy;
        Bashful bashful;
    
    private:
        int mumble;
    };

      如果Snow_White没有定义default constructor,就会有一个nontrivial constructor被合成出来,依序调用Dopey、Sneezy、Bashful的default constructors。然而如果Snow_White定义了下面这样的default constructor:

      

    //程序员所写的default constructor
    Snow_White::Snow_White(): sneezy(1024)
    {
        mumble = 2048;
    }

      它将会被扩张为:

      

    //编译器扩张后的default constructor
    Snow_White::Snow_White():sneezy(1024)
    {
        //插入member class object
        //调用其constructor
        dopey.Dopey::Dopey();
        sneezy.Sneezy::Sneezy(1024);
        bashful.Bashful::Bashful();
    
        //expilict user code
        mumble = 2048;
    }

      

      2."带有Default Constructor“的Base Class

        类似的道理,如果没有任何constructors的class派生自一个”带有default constructor“的base class,那么这个derived class的default constructor会被视为nontrivial,并因此需要被合成出来。它将调用上一层base classes的default constructor(如果是多继承,根据他们声明的顺序)。对一个后继的class而言,这个合成的constctor和一个”被显式提供的default constructor“没有什么差异。

        如果设计者提供多个constructors,但其中都没有default constructor呢?编译器会扩张现有的每一个constructors,将“用以调用所有必要之default constructors”的程序代码加进去。它不会合成一个新的default constructor,因为其他“由user所提供的constructors”存在的缘故。如果同时亦存在着“带有default constructor”的member class objects,那些default constructor也会被调用--在所有base class constructor之后。

      

      3.“带有一个virtual Function”Class

        另有两种情况,也需要合成出default constructor:

        1. class声明(或继承)一个virtual function  

        2. class继承自一个继承串链,其中有一个或多个的virtual base classes。

        假设类中还有虚函数,编译期间会发生两步扩张活动:

        1. 一个virtual function table(在cfont中被称为vtbl)会被编译出来,内放class的virtual functions地址。

        2. 在每个class object中,一个额外的pointer member(也就是vptr)会被编译器合成出来,内含相关之class vtbl的地址。

        对于那些未声明任何constructors的classes,编译器会为它们合成一个default constructor,以便正确地初始化每一个class object的vptr

      4.“带有一个virtual Base Class”的Class

      

      总结:有4种情况,会造成“编译器必须为未声明constructor 的classes合成default constructor”。它们分别是:

        “带有Default Constructor”的Member Class Object

        “带有Default Constructor”的Base Class

        “带有一个Virtual Function”的Class     

        “带有一个Virtual Base Class”的Class

        C++Standard把那些合成物称为implicit nontrivial default constructors。被合成出来的constructos只能满足编译器(而非程序)的要求。它之所以完成任务,是借着“调用member object或base object的default constructor”或是“为每一个object初始化其virtual function机制或virtual base class机制”而完成的。至于没有存在那4种情况而又没有声明任何constructor的classes,我们说它们拥有的是implicit trivial default constructors,它们实际上并不会被合成出来。

        在合成default constructor中,只有base class constructor和member class objects会被初始化。所有其他的nonstatic data member(如整数,整数指针、整数数组等等)都不会被初始化。这些初始化操作对程序而言或许有需要,但对编译器则非必要。如果一程序需要一个“把某指针设为0”的default constructor,那么提供它的人应该是程序员。

        C++新手一般有两个常见的误解:

        1. 任何class如果没有定义default constructor,就会被合成出一个来。

        2.编译器合成出来的default constructor会显式设定“class内每一个data member的默认值”  

        如你所见没一个是真的。

      

  • 相关阅读:
    树莓派4b 对于 Failed to execute command 的解决方案
    Windows 10 启用以太网/公共网络共享
    树莓派 配置 OMV 搭建 NAS(四) 文件夹共享
    树莓派 配置 OMV 搭建 NAS(三) 硬盘挂载
    树莓派 配置 OMV 搭建 NAS(二) 配置 OMV 5
    树莓派 系统配置
    树莓派/Debian 网线连接主机
    树莓派 配置 OMV 5 搭建 NAS(一) 安装 OMV 5
    Vmware 15 虚拟机挂载硬盘
    p9半幺群
  • 原文地址:https://www.cnblogs.com/vincently/p/4645543.html
Copyright © 2011-2022 走看看