码迷,mamicode.com
首页 > 编程语言 > 详细

重温《Inside The C++ Object Model》(2) --Default-Constructor的建构操作

时间:2015-01-03 10:43:33      阅读:248      评论:0      收藏:0      [点我收藏+]

标签:c++   面向对象   constructor   对象模型   指针   

//constructor/non-constructor的区别
class Foo
{
public:
    //Foo():val(0),next(NULL) {}
    int val;
    Foo *next;
};

void foo_bar()
{
    Foo bar;
    if ( bar.val && bar.next )
    {
        cout << bar.val << endl;
        printf("%p\n", bar.next);
        cout << "Un initialization" << endl;
    }
    else
    {
        cout << "Initialization" << endl;
    }
}

带有Default Constructor” 的 Member Class Object

(1)如果class A 内含有一个或一个以上的member-class-object, 那么class A 的每一个constructor必须调用每个member-classesdefault-constructor; 编译器会扩张已存在的constructor, 在其中安插一些代码使得user-code在被执行前先调用必要的default-constructors.

(2)C++语言要求以”member-objects 在 class 中的生命次序”来调用各个constructors.

 

假设有以下类:

class Dopey
{
public:
    Dopey();
    // ... etc ...
};
class Sneezy
{
public:
    Sneezy(int);
    Sneezy();
    // ... etc ...
};
class Bashful
{
public:
    Bashful();
    // ... etc ...
};

class Snow_White
{
public:
    Dopey dopey;
    Sneezy sneezy;
    Bashful bashful;
    // ... etc ...
private:
    int mumble;
};

如果Snow_White没有定义default-constructor, 就会有一个non-trivial-constructor被合成出来依序调用Dopey, Sneezy, Bashfuldefault-constructors. 然而如果Snow_White定义了下面这样的default-constructor:

Snow_White::Snow_White() : sneezy(1024)
{
    mumble = 2048;
}

它会扩张:

//编译器扩张后的default constructor
//C++伪码
Snow_White::Snow_White() : sneezy(1024)
{
    //插入 member class object
    //调用其 constructor
    dopey.Dopey::Dopey();
    sneezy.Sneezy::Sneezy();
    bashful.Bashful::Bashful();

    //explicit user-code
    mumble = 2048;
}

带有Default Constructor” 的 Base Class

在派生类中,如果同时存在member-class-object, 则先调用其base-class-constructor, 而后调用member-class-objectconstructor.

 

带有一个Virtual Function” 的 Class

以下的两种情况:

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

(2)class 派生自一个继承串链其中有一个或更多的virtual-base-classes.

都会有如下的扩张操作在编译期产生:

[1]一个 virtual-function-table(cfront中被称为vtbl)会被编译器生成内放classvirtual-function地址;

[2]在每一个class-object一个额外的pointer-member(也就是vptr)会被编译器合成出来内含相关的class-virtual-function-table(class-vtbl)的地址.

 

则假设有如下继承关系和代码:

技术分享

void flip(const Widget &widget)
{
    widget.flep();
}

widget.flip()的虚拟引发操作会被重新改写以使用widget的 vptr 和 vtbl中的flip()条目:

//widget.flip() 中的虚拟引发操作的改变
(*widget.vptr[1]).(&widget);

带有一个Virtual Base Class” 的 Class

假设有如下继承关系与代码:

技术分享

class X
{
public:
    virtual void memFunction() const
    {
        cout << "In X" << endl;
    }
};
class A : public virtual X
{
public:
    void memFunction() const
    {
        cout << "In A" << endl;
    }
};
class B : public virtual X
{
public:
    void memFunction() const
    {
        cout << "In B" << endl;
    }
};

class C : public A, public B
{
public:
    void memFunction() const
    {
        cout << "In C" << endl;
    }
};

void foo(const X *px)
{
    px -> memFunction();
}

int main()
{
    foo(new X);
    foo(new A);
    foo(new B);
    foo(new C);
}
/*
void foo(const X &rx)
{
    rx.memFunction();
}

int main()
{
    foo(X());
    foo(A());
    foo(B());
    foo(C());
}
*/

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

该功能则是靠”在派生类对象中的每一个虚基类中安插一个指针(_vbcX [virtual-base-class-X])”完成所有”经由reference/pointer来存取一个virtual-base-class”的操作都可以通过相关的指针来完成.foo()函数可以改写如下:

void foo(const X *px)
{
    //__vbcX表示由编译器产生的指针, 指向virtual-base-class-X
    px -> __vbcX -> memFunction();
}

重温《Inside The C++ Object Model》(2) --Default-Constructor的建构操作

标签:c++   面向对象   constructor   对象模型   指针   

原文地址:http://blog.csdn.net/zjf280441589/article/details/42360345

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!