在JNI中,經常會遇到這種場景:想在一個.h文件中寫一些全局變量,然後所有的cpp文件都能夠使用。如下有個a.h文件:
/* * a.h * * Created on: 2014-4-16 * Author: Administrator */ #ifndef A_H_ #define A_H_ int mAge = 0; void setAge(int age); int getAge(); #endif /* A_H_ */
下面是a.cpp文件:
/* * a.cpp * * Created on: 2014-4-16 * Author: Administrator */ #include "a.h" void setAge(int age){ mAge = age; } int getAge(){ return mAge; }然後有個main.cpp文件:
//============================================================================ // Name : Test2.cpp // Author : yan // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ #include#include "a.h" using namespace std; int main() { cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! setAge(22); cout<<"age = "< 編譯後報錯: E:\WorkSpaces\Eclipse_MinGW_C\Test2\Debug/../src/Test2.cpp:12: multiple definition of `main'
src\main.o:E:\WorkSpaces\Eclipse_MinGW_C\Test2\Debug/../src/main.cpp:13: first defined here
collect2.exe: error: ld returned 1 exit status
Build error occurred, build is stopped報multiple definition of的錯誤,解決方法是將變量搞成static。搞成static確實不報錯了,但這裡卻隱藏著一個天大的陷阱:
main.cpp如下:
#include#include "a.h" using namespace std; int main() { cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! setAge(22); cout<<"age = "<
打印出來的結果是這樣的:!!!Hello World!!!
age = 0
age = 555即雖然set成22了但是你訪問的話,直接拿來用mAge仍然是初始化的0.而如果使用get接口來訪問的數值是正確的。原因是:按書上說,static變量和一般全局變量一樣,都存儲在靜態存儲區。但static限定了變量訪問權限,只能讓本文件訪問,為什麼搞成static裡,在main裡有可以直接訪問了?原因是static的變量是在h文件而非cpp文件中聲明的。編譯的過程中,include的東西類似直接覆蓋的。所以直接訪問mAge得到的是初始化的值,不光怎麼set都沒用。這著實是個陷阱啊!!!
事實上這樣做也是不太安全的,更多時變量都在cpp文件聲明。因此更加安全的方法是:
1、變量聲明在cpp裡,聲明成普通的類型。然後通過set和get的方法進行設定和訪問。
2、變量聲明在cpp裡,然後在h文件裡將同樣的變量聲明成extern int mAge,這樣所有包含h文件的既可以直接訪問mAge。
3、static和extern是克星,一旦cpp文件裡變量聲明成static,那麼在h文件裡就不能extern了。
4、也可以h文件裡聲明普通變量,cpp裡extern,但不推薦。變量還是在cpp裡的好。
至少include “***.cpp”這種馊主意一般不要采用。
參考:
http://bbs.csdn.net/topics/390626289?page=1
http://blog.csdn.net/luo6620378xu/article/details/8511312