問題 1:
C++ 中的類能夠定義多個對象,那麼對象構造的順序是怎樣的?編程
問題 2:
對象構造順序會帶來什麼影響呢?函數
對象構造每每與構造函數相關聯,構造函數體有多是很是複雜的程序邏輯組成,不一樣類的構造函數中程序邏輯多是相互依賴的。當相互依賴發生時,對象的構造順序就變得尤其重要。
對於局部對象(包含靜態局部對象)code
- 當程序執行流到達對象的定義語句時進行構造
下面程序中的對象構造順序是什麼?對象
void code() { int i = 0; Test a1 = i; while( i < 3) Test a2 = ++i; if( i < 4 ) { Test a = a1; } else { Test a(100); } }
test_1.cppget
#include <stdio.h> class Test { private: int mi; public: Test(int i) { mi = i; printf("Test(int i) : %d\n", mi); } Test(const Test& obj) { mi = obj.mi; printf("const Test& obj : %d\n", mi); } }; int main() { int i = 0; Test a1 = i; while( i < 3) Test a2 = ++i; if( i < 4 ) { Test a = a1; } else { Test a(100); } return 0; }
輸出: Test(int i) : 0 Test(int i) : 1 Test(int i) : 2 Test(int i) : 3 const Test& obj : 0 結論: 局部對象的構造順序與程序的執行流相關
error.cpp編譯器
#include <stdio.h> class Test { private: int mi; public: Test(int i) { mi = i; printf("Test(int i) : %d\n", mi); } Test(const Test& obj) { mi = obj.mi; printf("const Test& obj : %d\n", mi); } int getMi() { return mi; } }; int main() { int i = 0; Test a1 = i; while( i < 3) Test a2 = ++i; goto End; // 注意這裏! Test a(100); End: printf("a.mi = %d\n", a.getMi()); return 0; }
g++ 輸出: test.cpp:30: error: jump to label ‘End’ test.cpp:28: error: from here test.cpp:29: error: crosses initialization of ‘Test a’ vc2010 編譯輸出: error.cpp(34) : warning C4533: 「goto a」跳過了「End」的初始化操做 error.cpp(33) : 參見「a」的聲明 error.cpp(34) : 參見「End」的聲明 vc2010 運行輸出: Test(int i) : 0 Test(int i) : 1 Test(int i) : 2 Test(int i) : 3 a.mi = 4076341
發生了什麼?it
對於堆對象io
- 當程序執行流到達 new 語句時建立對象
- 使用 new 建立對象將自動觸發構造函數的調用
下面程序中的對象構造順序是什麼?編譯
void code() { int i = 0; Test* a1 = new Test(i); while( ++i < 10 ) if( i % 2 ) new Test(i); if( i < 4 ) new Test(*a1); else new Test(100); return 0; }
#include <stdio.h> class Test { private: int mi; public: Test(int i) { mi = i; printf("Test(int i) : %d\n", mi); } Test(const Test& obj) { mi = obj.mi; printf("const Test& obj : %d\n", mi); } int getMi() { return mi; } }; // 這裏在 new 以後沒有 delete,僅爲演示 int main() { int i = 0; Test* a1 = new Test(i); while( ++i < 10 ) if( i % 2 ) new Test(i); if( i < 4 ) new Test(*a1); else new Test(100); return 0; }
輸出: Test(int i) : 0 Test(int i) : 1 Test(int i) : 3 Test(int i) : 5 Test(int i) : 7 Test(int i) : 9 Test(int i) : 100 結論: 堆對象的構造順序與程序的執行流相關。堆對象一樣受到程序執行流的影響,具體可參考局部對象中的分析。
對於全局對象class
- 對象的構造順序是不肯定的
- 不一樣的編譯器使用不一樣的規則肯定構造順序
test.h
#ifndef _TEST_H_ #define _TEST_H_ #include <stdio.h> class Test { public: Test(const char* s) { printf("%s\n", s); } }; #endif
t1.cpp
#include "test.h" Test t1("t1");
t2.cpp
#include "test.h" Test t2("t2");
t3.cpp
#include "test.h" Test t3("t3");
test.cpp
#include "test.h" Test t4("t4"); int main() { Test t5("t5"); return 0; }
g++ 輸出: t3 t2 t1 t4 t5 vc2010 輸出: t4 t1 t2 t3 t5
警示: 儘可能避開全局對象,儘可能避開全局對象的相互依賴
- 局部對象的構造順序依賴於程序的執行流
- 堆對象的構造順序依賴於 new 的使用順序
- 全局對象的構造順序是不肯定的
以上內容參考狄泰軟件學院系列課程,請你們保護原創!