浅出C++对象模型——理解构造函数、析构函数执

系统 2360 0

本文主要说明对象创建时构造函数的执行顺序,对象成员的初始化顺序;对象销毁时析构函数的执行顺序,对象成员的销毁顺序。


“对象的构造从类层次的最根处开始,在每一层中,首先调用基类的构造函数,然后调用成员对象的构造函数。析构则严格按照与构造相反的次序执行,该次序是唯一的,否则编译器将无法自动执行析构过程。

一个有趣的现象是,成员对象初始化的次序完全不受它们在初始化表中次序的影响,只由成员对象在类中声明的次序决定。这是因为类的声明是唯一的,而类的构造函数可以有多个,因此会有多个不同次序的初始化表。如果成员对象按照初始化表的次序进行构造,这将导致析构函数无法得到唯一的逆序。”(引用自 References[1]

从这里看,每种语言特性的存在必有其原因,学习这些特性就是理解这些特性存在的原因。

下面的一段代码是对上面这段话的说明,其中有 4 个类 Foo,Bar,Base,Derived ,它们的构造函数、拷贝构造函数、析构函数都有信息输出。

    #include <iostream>
using namespace std;

class Foo
{
public:
        Foo() { cout << "Foo constructor" << endl; }
        Foo(const Foo &foo) { cout << "Foo copy constructor" << endl; }
        ~Foo() { cout << "Foo deconstructor" << endl; }
};

class Bar
{
public:
        Bar() { cout << "Bar constructor" << endl; }
        Bar(const Bar &bar) { cout << "Bar copy constructor" << endl; }
        ~Bar() { cout << "Bar deconstructor" << endl; }
};

class Base
{
public:
        Base() { cout << "Base constructor" << endl; }
        ~Base() { cout << "Base deconstructor" << endl; }
};

class Derived : public Base
{
public:
        Derived() { cout << "Derived constructor without arguments" << endl; }
        Derived(const Foo &foo, const Bar &bar);
        Derived(const Bar &bar, const Foo &foo);
        ~Derived() { cout << "Derived deconstructor" << endl; }

private:
        Foo m_foo;
        Bar m_bar;
};

Derived::Derived(const Foo &foo, const Bar &bar) :
        m_foo(foo),
        m_bar(bar)
{
        cout << "Derived constructor with argument[Foo foo, Bar bar] passed by references" << endl;
}

Derived::Derived(const Bar &bar, const Foo &foo) :
        m_bar(bar),
        m_foo(foo)
{
        cout << "Derived constructor with argument[Bar bar, Foo foo] passed by references" << endl;
}

int main (int argc, char** argv)
{
        Foo foo;
        Bar bar;

        cout << "test case 1:" << endl;
        Derived deri_1;  //  (1)

        cout << "test case 2:" << endl;
        Derived deri_2(foo, bar);   //  (2)

        cout << "test case 3:" << endl;
        Derived deri_3(bar, foo);   //  (3)

        cout << "test case end" << endl;

        return 0;
}
  

执行结果是:

浅出C++对象模型——理解构造函数、析构函数执行顺序


打印出的信息可分为几部分:

(1)创建对象 foo bar ,执行 Foo,Bar 的构造函数

(2)TestCase1: 创建对象 deri_1,首先执行基类Base 的构造函数,其次执行成员 m_foo,m_bar 的构造函数来构造成员,最后调用自身的构造函数 ( 无参数 )

(3)TestCase2: 创建对象 deri_2,调用顺序与case1 顺序相同。

(4)TestCase3: 创建对象 deri_3,调用顺序与case1 顺序相同。注意到 deri_2,deri_3 的创建执行的是不同的 Derived 构造函数,虽然构造函数参数的顺序不同,但是构造成员的顺序是相同的。

(5)销毁对象 deri_3,deri_2,deri_1 ,析构函数执行顺序相同,与构造对象的顺序相反。 C++ 标准规定以对象声明相反的顺序销毁这些对象。

(6)销毁对象 bar,foo


编译运行环境:

    $ uname -a
Linux localhost.localdomain 2.6.18-308.el5 #1 SMP Fri Jan 27 17:17:51 EST 2012 x86_64 x86_64 x86_64 GNU/Linux

$ g++ --version
g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-52)
  

References:

[1] 高质量 C++ 编程指南 : http://oss.org.cn/man/develop/c&c++/c/c.htm

[2] http://stackoverflow.com/q/15948381/1145750

转载本文请注明作者和出处 http://garyelephant.me ,请勿用于任何商业用途!

Author:GaryGao 关注互联网、自动化、软件团队






浅出C++对象模型——理解构造函数、析构函数执行顺序


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论