zoukankan      html  css  js  c++  java
  • Default Constructor的构造操作

    Default Constructor的构造操作

           C++ Annotated Reference Manual书中的Section 12.1说过:default constructor 只有在编译器需要的时候才会被编译器合成出来。

           C++ Standard修改了C++ ARM的说法,但实际上的行为是一样的。C++ Standard[ISO-C++95]的Section 12.1说到:对于class X,如果没有任何user-declared constructor,那么会有一个default constructor被隐式(implicitly)声明出来。不过这样的隐式声明的default constructor将是一个trivial(无用的)constructor。也就是所谓的implicit trivial default constructor,它们实际上并不会被合成出来。

           那到底声明才是C++ ARM所说的编译器需要的情况呢?

    第一,“带有Default Constructor”的Member Class Object

           如果一个class X没有任何constructor,但它有至少一个member object,而这个member object对应的class有default constructor,那么编译器就需要为class X合成一个default constructor。不过这个合成操作只有在constructor被调用的时候才会发生。

           举个例子:

           class Foo { public : Foo(), Foo(int)…};

           class Bar {pubcli Foo foo; char *str;};

           void foo_bar()

           {

                  Bar bar; // Bar:foo 必须在此处初始化。

    }

    被合成的default constructor看起来可能像这样(省略this指针):

    inline

    Bar::bar()

    {

           foo.Foo::Foo();

    }

    第二,“带有Default Constructor”的Base Class

           与第一点类似,如果一个没有任何constructor的class派生自一个“带有Default Constructor”的base class,那么编译器会为这个derived class合成一个default constructor,它将调用上一层base classes的default constructor(根据它们声明顺序)。如果同时存在第一点和第二点的情况,则member class objects constructor会在所有base class constructor之后再调用。

    第三,“带有至少一个Virtual Function”的Class

           编译器会为每一个“带有至少一个Virtual Function”的class object的vptr(指向virtual table)设定初值。对于一个没有任何constructor的class,编译器会为它合成一个default constructor,以便正确地初始化每一个class object的vptr。

    第四,“带有至少一个Virtual Base Class”的Class

           Virtual base class的实现法在不同的编译器之间有极大地差异。然而,每一种实现法的共同点在于必须使virtual base class在其每一个derived class object中的位置,能够于执行期准备妥当。

           举个例子:

           class X { public: int i;};

           class A : public virtual X {public: int j;};

           class B : public virtual X {public: double d;};

           class C : public A, public B {public: int k;};

           // 无法在编译期决定pa->X::i的实际偏移位置

           void foo(const A* pa) {pa->i = 1024;}

           main()

           {

                  foo(new A);

    foo(new B);

    }

    编译器无法固定住foo()之中“经由pa而存取的X::i”的实际偏移位置,因为pa的真正类型可以改变。编译器必须改变“执行存取操作”的那些代码,使X::i可以延迟至执行期才决定下来。

    对于一个没有任何constructor的class,编译器会为它合成一个default constructor,在这个default constructor中会安插那些“允许每一个virtual base class的执行期存取操作”的代码。

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

    注意

    1、在合成的default constructor中,只有base class subobjects和member class objects会被初始化。所有其他的nonstatic data member(如整数,整数指针,整数数组等等)都不会被初始化。这些初始化操作对于编译器都是非必要的,提供这些初始化操作的应该是程序员而不是编译器。

    2、不是任何没有定义default constructor的class都会生成一个implicit default constructor。

    3、编译器合成的default constructor不会显示设定“class 内每一个data member的默认值”。

  • 相关阅读:
    iBatisnet 1.5版本的配置文件的几个变化
    使用Trace时要注意
    无刷新转页面?
    无刷新“页面跳转”问题一:与AtlasToolKit协同工作
    Assembly的Release与Debug
    iBatis.Net系列(四) iBatisNet API基础
    Atlas 调用web service
    无刷新“页面跳转”
    iBatis.Net系列(六) ResultMap
    在GridView中格式化时间字段
  • 原文地址:https://www.cnblogs.com/wuhaowinner/p/default_constructor.html
Copyright © 2011-2022 走看看