linker對鏈接順序要求很嚴格,如果順序有誤,多半就會報undefined reference to xxxxxx的錯誤
文件目錄:
代碼:
main.cpp
1 #include "Test.h" 2 3 using namespace std; 4 5 int main() 6 { 7 Test::testLiftOff(); 8 return 0; 9 }
Test.cpp
1 #include "Test.h" 2 3 #include "LiftOff.h" 4 5 #include <zthread/Thread.h> 6 7 #include <iostream> // std::cout 8 9 void Test::testLiftOff() 10 { 11 using namespace ZThread; 12 13 try { 14 for (int i = 0; i < 5; ++i) 15 { 16 Thread th(new LiftOff(10, i)); 17 } 18 std::cout << "waiting for lift off" << std::endl; 19 } catch (Synchronization_Exception &e) { 20 std::cerr << e.what() << std::endl; 21 } 22 } 23 24 Test::Test() 25 { 26 //ctor 27 } 28 29 Test::~Test() 30 { 31 //dtor 32 }
LiftOff.cpp
1 #include "LiftOff.h" 2 3 #include <iostream> 4 5 using namespace std; 6 7 LiftOff::LiftOff(int countDown_, int id_) 8 :countDown(countDown_), id(id_) 9 { 10 // do nothing 11 } 12 13 LiftOff::~LiftOff() 14 { 15 cout << "LiftOff" << id << " destroyed" << endl; 16 } 17 18 void LiftOff::run() 19 { 20 while (countDown--) 21 cout << id << " count: " << countDown << endl; 22 cout << id << "LiftOff!" << endl; 23 }
Test.h
1 #ifndef TEST_H 2 #define TEST_H 3 4 5 class Test 6 { 7 public: 8 static void testLiftOff(); 9 10 private: 11 Test(); 12 ~Test(); 13 }; 14 15 #endif // TEST_H
LiftOff.h
1 #ifndef LIFTOFF_H 2 #define LIFTOFF_H 3 4 #include <zthread/Runnable.h> 5 6 class LiftOff : public ZThread::Runnable 7 { 8 public: 9 LiftOff(int countDown_, int id_); 10 ~LiftOff(); 11 void run(); 12 private: 13 int countDown; 14 int id; 15 }; 16 17 #endif // LIFTOFF_H
顯然,main.cpp 通過 Test.h 引用 Test.cpp 的 implementation 。 說人話? 好吧 。。。 具體來說就是linker在發現main.cpp 中的 Test::testLiftOff() 調用的時候, 需要去找Test::testLiftOff()的implementation,去哪找?當然是Test.cpp中,編譯為obj文件后,其實就是main.o 依賴於 Test.o
我們把這種關系描述為 main.o < Test.o
類似的還有 Test.o < LiftOff.o 、 Test.o < zthread_win3.a
總的原則就是:如果A.o依賴於B.o,那么在linker命令中,A.o必須在B.o的左邊(可以不相鄰)
所以在鏈接的時候,命令為:
g++ -o test.exe main.o Test.o LiftOff.o -s zthread_win32.a // linker command 1
其實,只要順序不違反上面的關系定義,后面的順序是可以任意調整的,例如,實際上LiftOff.o與-s zthread_win3.a的順序調一下也是可以的
g++ -o test.exe main.o Test.o -s zthread_win32.a LiftOff.o // linker command 2
總結:
你編譯上面的代碼為:
g++ -c *.cpp
鏈接的時候上面給出的linker command 1、linker command 2任意選一個都行
另外:
事實上,在linux下,由於ZThread依賴於Posix Thread Library,在 -s zthread_xxx.a之后還需要-lpthread來加載Posix Thread Library,也是這個原因,見這篇隨筆