Posted on 2007-08-30 10:28
宝杉 阅读(185)
评论(0) 编辑 收藏 引用 所属分类:
C++
析构函数
构造函数初始化表:构造函数特殊的初始化方式“初始化表达式表”(简称初始化表)。
初始化表位于函数参数表之后,却在函数体 {} 之前。这说明该表里的初始化工作发生在函数体内的任何代码被执行之前。
规则
u 如果类存在继承关系,派生类必须在其初始化表里调用基类的构造函数。
u 类的const常量只能在初始化表里被初始化,因为它不能在函数体内用赋值的方式来初始化。
u 类的数据成员的初始化可以采用初始化表或函数体内赋值两种方式,这两种方式的效率不完全相同。
效率
1 内部成员:
初始化表和函数体内赋值都可以,但效率不完全相同,但后者更为清晰直观。
例子:
class F
{
public:
F(int x, int y); // 构造函数
private:
int m_x, m_y;
int m_i, m_j;
}
F::F(int x, int y)
: m_x(x), m_y(y)
{
m_i = 0;
m_j = 0;
}
|
F::F(int x, int y)
{
m_x = x;
m_y = y;
m_i = 0;
m_j = 0;
}
|
示例9-2(c) 数据成员在初始化表中被初始化 示例9-2(d) 数据成员在函数体内被初始化
两种方式效率区别不大。
2 非内部成员:
只能用初始化表,提高效率。
例子:
class A
{…
A(void); // 无参数构造函数
A(const A &other); // 拷贝构造函数
A & operate =( const A &other); // 赋值函数
};
class B
{
public:
B(const A &a); // B的构造函数
private:
A m_a; // 成员对象
};
比较与分析:
B::B(const A &a)
: m_a(a)
{
…
}
|
B::B(const A &a)
{
m_a = a;
…
}
|
1 B类构造函数的初始化里,调用了A类的拷贝构造函数。
2 B类构造初始化里,隐藏了以下几个步骤:
先创建了a对象,调用了A类的无参数构造函数;
把a赋值给m_a,调用了A类的赋值函数;
深入探讨:
构造和析构的次序?
构造从最深处的基类开始的,先一层层调用基类的构造函数,然后调用成员对象的构造函数。
而析构函数严格按照构造函数相反的次序执行,该次序唯一,以便让编译器自动执行析构函数。
特别之处是,成员对象初始化次序不受构造函数初始化表次序影响,由在类中声明的次序决定。而类声明是唯一的,构造函数却可能有多个,所以有多个不同次序函数初始化表。如果按照构造函数的次序构造,那么解析函数不能得到唯一的逆序。