您的位置:首页 > 编程语言 > C语言/C++

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

2013-04-12 14:49 537 查看
本文主要说明对象创建时构造函数的执行顺序,对象成员的初始化顺序;对象销毁时析构函数的执行顺序,对象成员的销毁顺序。

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

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

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

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

[cpp] view
plaincopy

#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;

}

执行结果是:



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

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

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

(3) Test Case 2:创建对象deri_2,调用顺序与case 1顺序相同。

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

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

(6) 销毁对象bar,foo。

编译运行环境:

[plain] view
plaincopy

$ 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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐