Chinaunix首页 | 论坛 | 博客
  • 博客访问: 328894
  • 博文数量: 79
  • 博客积分: 2466
  • 博客等级: 大尉
  • 技术积分: 880
  • 用 户 组: 普通用户
  • 注册时间: 2006-02-07 16:47
文章分类

全部博文(79)

文章存档

2014年(3)

2012年(7)

2011年(14)

2010年(2)

2009年(2)

2008年(2)

2007年(18)

2006年(31)

分类: C/C++

2011-08-07 20:43:38

C++对象构造的顺序

1. Virtual base classes are initialized, in the order they appear in the base list.
2. Nonvirtual base classes are initialized, in declaration order.
3. Class members are initialized in declaration order (regardless of their order in the initialization list).
4. The body of the constructor is executed.

用下面的例子解释一下这个规则:

struct V { V() { printf("V()\n"); } };
struct B1: virtual public V { B1() { printf("B1()\n"); } };
struct B2: virtual public V { B2() { printf("B2()\n"); } };
struct C: public V { C() { printf("C()\n"); } };
struct M1 { M1(int) { printf("M1()\n"); } };
struct M2 { M2(int) { printf("M2()\n"); } };
struct D: public C, public B2, public B1 {
    M2 m2;
    M1 m1;
    D():m1(0), m2(1) { printf("D()\n"); }
};

int
main() {
    D d;
}

程序的输出是
V()
V()
C()
B2()
B1()
M2()
M1()
D()

首先,虚基类先构造,所以V()先出现。
然后,D的基类C还有一个非虚基类V,这是第二个V()。
接下来是所有非虚基类的构造,按声明从左到右的顺序:C, B2, B1。
然后是成员的构造,按声明的顺序(而__不是__初始化列表里的顺序):M2, M1。
最后是最派生类本身的构造函数被执行。

注意上面成员函数的构造顺序是重要的。如果m2的构造过程要求m1已经正确构造完成,上面的代码就会出错。例如:
struct D {
    char m2;
    char *m1;
    D():m1(new char[2]), m2(m1[0]) { printf("D()\n"); }
};

int
main() {
    D d;
}
这个程序一定会崩溃。因为虽然m2在初始化表里排在后面,但m2声明在前,所以一定是先构造m2。
也是由于同样的原因,g++对这样的代码在-Wall选项下是会报warning的。
阅读(1591) | 评论(0) | 转发(0) |
0

上一篇:Koenig lookup

下一篇:成员函数查找的步骤

给主人留下些什么吧!~~