2012年11月13日 星期二

c++ static 修飾詞

最近寫基因演算法的project,有需要使用到C++ class的static variable,因為我之前這個東西怎麼寫都會出錯,這次好不容易在強者陳仕勳(GodGodMouse)的指導下成功寫出可以用的static,在這裡記錄一下怎麼使用C++的Static(是說這些文章也多到滿出來了)。

靜態物件static的標記包括:在主體程式中使用,在函式中使用,和在class中作為靜態資料使用。
總歸三種使用方式,都是要在程式的各處中使用共有的一份資料,下面針對三種使用方式,分別寫明使用方法及使用的時機: 

1. Main程式:

在global 的地方使用static,可以讓該變數由程式的全域變數變成檔案內的全域變數,使用static的全域變數幾乎永遠是好習慣,畢竟其他程式設計師在用你的程式時只想把你的程式當黑箱子,要是哪個全域變數名字相衝……那大概不是一兩個幹字可以解決的問題,例如下文中的debug變數,我每個檔案都想要有debug變數,這時就要加上static。
簡單的例子,我們幾個cpp檔裡面都有一個debug變數(總不能main裡的叫maindebug,gui裡的叫guidebug吧?),如果不加上static
//main.cpp
int debug  = 0; 
//src1.cpp
int debug  = 0; 
這樣在最後編譯的時候,g++ main.o src1.o的階段,就會回傳錯誤,因為debug在這裡被重複定義。 因此,請為全域變數加上static。
Static int debug = 0
或者,與static相對的就是extern,宣告變數是在別的檔案裡有定義,這時候不能再給初始值(因為初始值是從別的檔案來的):
extern char* filename;

2. 在函數裡使用:

在函數裡加上static的變數,不同於一般的變數「在函數執行時起始,於函數終結時清除」,static變數在程式一執行時即被宣告。我想這個已經芭樂到不能再芭樂的地步了,例子也不勝枚舉,如果我們要輸出某函數被call幾次,請愛用static。
Void function(){
 static int i=0;
 cout << ++i << endl;
}

3. 在class裡使用:

在class裡使用,其功用在於,這個class產生的任何一個object(or instance if you like),都可看到static的變數或函數。 比如說我project寫的基因演算法的程式,經由隨機產生了10000個子代,每個子代都要對某一筆測試資料進行處理,看看結果好不好;這時候當然不可能每一個子代都保留一份測試資料的副本(記憶體不用錢也不是這樣花的吧…),就要用static的方式保存資料,讓每個子代都能看到。
在class裡面用會複雜一點,假設現在有一個叫static_test的class,架構如下:
//static_test.h
class static_test { 
public:
    static int static_var;
    static void output();
    int i;
};
所以我們宣告了一個static的integer跟一個static 的function,在.h宣告中,大部分的東西是一樣的。
但在定義式裡,就有些不同,由於static物件在是class共有的一部分,宣告class物件時並不會初始化static的物件,因此在.cpp裡面第一件事就是先初始化static物件:
//static_test.cpp
int static_test::static_var;
要不要給初始值沒什麼關係,但這行指明:static_test中有一個static_var,不寫這行編譯時會出現undefined reference to static_var。 取用static物件時,也要用'::'指明:我要取用static_test的物件,例如:
cout << static_test::static_var << endl;
static_test::static_var = 10;
static function是類似的事情,每一個class都可以取用這個function,但static function裡面,只能用到static的member,因為它並非任何一個object的function,自然不能取用其中的內容,就如文中的output()不能取用 i 這個變數。
據說static member最常用的地方是統計目前程式中生成了幾個object,在contructor中對static member+1,destruct的時候-1,不過作者到目前還是沒遇到相關的場合,所以…就算了吧,能用就好。

 4. 致謝: 

本篇文章,感謝陳仕勳(GodGodMouse)強者的指導。

1 則留言: