第21课 对象的构造顺序

问题:

C++中的类可以定义多个对象,那么对象的构造顺序是怎么样的?

对象的构造顺序一:

示例如下:

 1 #include <stdio.h>
 2 
 3 class Test
 4 {
 5 private:
 6     int mi;
 7 public:
 8     Test(int i)
 9     {
10         mi = i;
11         printf("Test(int i): %d\n", mi);
12     }
13     Test(const Test& obj)
14     {
15         mi = obj.mi;
16         printf("Test(const Test& obj): %d\n", mi);
17     }
18 };
19 
20 int main()
21 {
22     int i = 0;
23     Test a1 = i;
24         
25     while( i < 3 )
26     {
27         Test a2 = ++i;
28     }
29         
30     if( i < 4 )
31     {
32         Test a = a1;
33     }
34     else
35     {
36         Test a(100);
37     }
38 
39     return 0;
40 }

运行结果如下:

 添加上goto语句,运行结果如下:

引入goto使得30-37行的程序被跳过,因此a对象就不会被构造了。

执行流和局部对象的构造息息相关。

非法改变程序的执行流,可能引起灾难性的错误。

示例如下:

我们使用goto跳过了34行,在36行又调用这个a对象,这时编译器就会报错。

g++编译器在这种情况下会报错,但是其他编译器却不一定。

VC下的编译运行结果如下:

可见编译器之间的行为并不一样。

对象的构造顺序二:

示例程序:

 1 #include <stdio.h>
 2 
 3 class Test
 4 {
 5 private:
 6     int mi;
 7 public:
 8     Test(int i)
 9     {
10         mi = i;
11         printf("Test(int i): %d\n", mi);
12     }
13     Test(const Test& obj)
14     {
15         mi = obj.mi;
16         printf("Test(const Test& obj): %d\n", mi);
17     }
18     int getMi()
19     {
20         return mi;
21     }
22 };
23 
24 int main()
25 {
26     int i = 0;
27     Test* a1 = new Test(i); // Test(int i): 0
28         
29     while( ++i < 10 )
30         if( i % 2 )
31             new Test(i); // Test(int i): 1, 3, 5, 7, 9
32         
33     if( i < 4 )
34         new Test(*a1);
35     else
36         new Test(100); // Test(int i): 100
37         
38     return 0;
39 }

运行结果如下:

 堆对象的创建也会受到goto语句的影响。

 对象的构造顺序三:

全局对象的构造顺序是不确定的。

示例:

 1 #ifndef _TEST_H_
 2 #define _TEST_H_
 3 
 4 #include <stdio.h>
 5 
 6 class Test
 7 {
 8 public:
 9     Test(const char* s)
10     {
11         printf("%s\n", s);
12     }
13 };
14 
15 #endif
1 #include "test.h"
2 
3 Test t1("t1");
1 #include "test.h"
2 
3 Test t2("t2");
1 #include "test.h"
2 
3 Test t3("t3");
1 #include "test.h"
2 
3 Test t4("t4");
4 
5 int main()
6 {
7     Test t5("t5");
8 }

全局对象的构造一定是在main函数执行前完成的,这和程序的执行流没有关系。因为main函数执行前不存在执行流的概念。

如果出现多个全局对象,则他们的构造顺序就不确定了。

运行结果如下:

 VC下的编译情况如下:

运行结果如下:

由以上现象可以看到,全局对象的构造顺序是不确定的,不同的编译器是不一样的。

因此,我们在开发的时候要避开全局对象之间的相互依赖。

小结:

猜你喜欢

转载自www.cnblogs.com/wanmeishenghuo/p/9569537.html