1

我有這些靜態成員初始化C++類的麻煩。 查看我的代碼以獲取更多信息。C++靜態成員初始化與編譯器鏈接混淆。怎麼解決?

header.h

#ifndef HEADER_H 
#define HEADER_H 
#include <string> 
using namespace std; 
class Staff{ public: static string str;}; 
class Boss{ public: static string str;}; 
#endif 

staff.cpp

#include "header.h" 
string Staff::str = "(staff)"; 

boss.cpp

#include "header.h" 
string Boss::str = "I call " + Staff::str; 

的main.cpp

#include <iostream> 
#include "header.h" 
int main(){cout << Boss::str << endl;} 

這裏是與不同的結果多編譯代碼:

預編譯:

g++ -c boss.cpp 
g++ -c staff.cpp 
ar rcs lib.a boss.o staff.o 
ar rcs rlib.a staff.o boss.o 

編譯,運行和結果:

g++ main.cpp staff.cpp boss.cpp ; ./a.out 
==> I call (staff) 
g++ main.cpp boss.cpp staff.cpp ; ./a.out 
==> segmentation fault (core dumped) 
g++ main.cpp lib.a ; ./a.out 
==> segmentation fault (core dumped) 
g++ main.cpp rlib.a ; ./a.out 
==>segmentation fault (core dumped) 

我想用庫歸檔,而不是在編譯時混淆巨大的對象。 幫我解決它們。

謝謝。

回答

9

單獨翻譯單元中靜態變量的初始化順序未定義。您的兩個源文件組成兩個獨立的翻譯單元,每個翻譯單元定義一個變量。當Staff::str尚未初始化時,嘗試使用Staff::str來初始化Boss::str時可能發生分段錯誤。

爲了解決這個問題,在同一個翻譯單元定義他們兩個:

#include "header.h" 
string Staff::str = "(staff)"; 
string Boss::str = "I call " + Staff::str; 

或者讓自己的初始化相互獨立:

std::string Staff::get_str() { 
    return "(staff)"; 
} 

string Staff::str = Staff::get_str(); 

string Boss::str = "I call " + Staff::get_str(); 

從你的前兩個例子,它出現初始化順序與鏈接順序有關,但您不能依賴該順序。

1

全局變量在獨立翻譯單元中的初始化順序未定義。您可以將它們包裝在一個功能中以使其發揮作用:

class Staff{ public: static & string str();}; 
class Boss{ public: static & string str();}; 

string & Staff::str() 
{ 
    static string s = "(staff)"; 
    return s; 
} 

string & Boss::str() 
{ 
    static string s = "I call " + Staff::str(); 
    return s; 
}