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

    default constructor 会在需要的时候被编译器产生出来 

    ----<<Inside C++ Object Model>>

    一切从这开始, 是在谁需要的时候? 考察以下代码:


    class Foo{public: int val; Foo *pnext};


    void FooBar()
    {
    //Foo Object 须在此初始化
    Foo bar;
    if(bar.val || bar.pnext)
    //do something...
    }


    编译器不会为其产生一个 default constructor, 因为这是程序需要而不是编译器需要, 程序有需要, 那是程序员的责任, 因此上述代码不会合成一个 default constructor.


    那么在那些情况下是编译器需要构建 default constructor 的情况呢?


    1. 带有 Default Constructor 的 Member Class Object
    但出现一个问题, 怎样防止在不同模块中生成多个 default constructor?
    解决方法是, 把合成的 default constructor 都以 inline 的方式完成, inline 函数有静态连接, 不会被文件以外看到, 如果函数太复杂, 不适合做出一个 inline, 编译器则会做出一个 explicit non-inline static 实体. 考察以下代码:


    class Foo{public: Foo(){} Foo(int){/* do something */}...};
    class Bar{private: Foo foo; char *pstr;};


    void FooBar()
    {
    //bar Object 需要在此初始化
    Bar bar


    if(str)...
    }


    此例中, 编译器会产生 bar 的 default constructor 来调用 class Foo 的 default constructor 初始化 Bar::foo, bar 的 default constructor 中, 并不存在初始化 str 的代码, 因为那是程序员的责任.


    那么如果程序员已定义了用来初始化 str 的 constructor, 如:
    Bar::bar(){str = 0;}


    那么编译器会怎样做呢, 它会扩展你的代码, 在你的代码之前添加必要的 default constructor 即:
    //你看上去的
    Bar::bar(){str = 0;}


    //实际可能是
    Bar::bar(){Foo::Foo(); str = 0;}


    问题又来了, 假如 class 中 有多个 member object 嗷嗷待哺呢?
    结果是, 编译器会按照其声明的顺序初始化.


    2. 带有 Default Constructor 的 Base Class
    我倾向于用一个例子说明问题:


    class Member{public: Member(){std::cout << "member ";}} 


    class Base1 {
    public: Base1(){public: std::cout << "base1";}
    private: Member m;};


    public: Base2(){public: std::cout << "base2";}
    private: Member m;};


    class Derived:public Base2, public Base1
    {public: Derived(){std::cout << "derived";}}


    int main(){Derived d; return 0;}


    输出结果是: 
    member      //由程序员定义的 Base2::Base2() 被扩展
    base2       //由此可见, 调用顺序由继承顺序有关
    member 
    base1
    derived     //编译器扩展的代码结束, user code 开始运行


    前四段代码是编译器在用户定义的 constructor 代码中, std... 之前插入的调用 base constructor 的代码产生的结果, 按照继承的顺序调用相应的 constructor.


    3. 带有 Virtual Function 的 Class
    在带有 virtual function 的 class 中, 如果缺少合适的 constructor, 编译器会进行两个扩张:
    1) 一个 virtual function table 会被创建出来, 内放 class 的 virtual
    function 地址
    2) 在每一个 class object 中, 一个额外的 pointer member(即 vptr) 会被创建出来, 内含相关的 vtbl 地址
    所以编译器会产生一个 default constructor 来初始化 vtbl 与 vptr


    4. 带有Virtual Base Class 的 Class
    考察以下代码:
    struct X{int i;};
    struct A:public virtual X{int j;};
    struct B public virtual X{int k;};
    struct C:public A, public B{double d;} 


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


    int main()
    {
    Foo(new A);
    Foo(new C);
    }


    编译器无法确定 Foo() 中 _i 的实际 _i 移动的位置, 因为 pa 可以改变, 要延迟到执行期才能固定下来, 因此此动作要通过存取 virtual base class 的相关指针来完成, 因此编译器实际可能做的事情是把函数扩充为:
    void Foo()(const A *pa){pa->__vbcX->i = 1024;}


    没错, 那么 __vbcX 就需要在 object 被建构之前被初始化, 编译器就需要为它合成一个 default constructor.


    新手的误解:
    1) 若 class 没有定义一个 default constructor, 那么编译器就会合成一个出来;


    2) 编译器合成出来的 default constructor 会明确设定 class 内每一个 data member 的初始值.


    当然, 以上观念都是错的!
  • 相关阅读:
    字符串格式化及操作操作
    操作文件
    python学习笔记(数据类型)
    抓包工具之—charles碎言碎语
    jmeter之关联操作
    eclipse插件Maven添加依赖查询无结果的解决方法(Select Dependency doesn't work)
    java使用this关键字调用本类重载构造器
    无法安装Windows Live“OnCatalogResult:0x80190194”错误的解决方法
    JavaScript笔试必备语句
    VS2015详细安装步骤
  • 原文地址:https://www.cnblogs.com/wuOverflow/p/4098671.html
Copyright © 2011-2022 走看看