2009年2月13日 星期五

類別裡面的const"變數"

最近被問到,類別裡面的const變數撰寫方式,乾脆整理const的一些規則,首先,const應該是常數不是變數,所有的常數只能被初值化,不能被賦值,所以只能寫在建構式的initial-list中,一般常數的設計方式有以下幾種:

1. 用#define 這個方式是最暴力的,被define的常數本身不隸屬任何類別,曾經看過這樣的程式碼,寫在程式的任何地方意義都是一樣的:

// 寫在裡面
class ABC
{
#define PI 3.14159
};

#define PI 3.14159
class ABC
{
};

所以,嚴格說來,這不算"類別裡面的const變數"。

2. 用const修飾的變數
class ABC
{
const float PI;
};
這種方式只能在建構式的initial-list初值化,錯過這個機會,變數值就不知道是什麼了

ABC::ABC()
: PI(3.14159) // 這裡
{
}

3. 類別內共用的常數變數,可以用static修飾,讓所有物件共用這個"常數"
class ABC
{
static const int SONG=123;
};

用這種方法可以直接在類別宣告裡面給初值,但是有一個限制,這種方法僅限於型別是整數的型態(至少VC是這樣的),如果想要用非整數的型態,要用這樣的寫法
class ABC
{
static const float PI;
};
在CPP某處加:
const float ABC::PI=3.14159;
為什麼要加在CPP? 只是因為不能讓"const float ABC::PI=3.14159;"被編譯兩次以上,如果放在.h有可能發生,而造成編譯錯誤。

4. 使用enum
class ABC
{
enum { SONG=134, STOP=1113 };
};

用這種方法,只要enum區段合法,任何時候都可以用 ABC::SONG 這樣的寫法來取得其值,不過限制是,enum只支援整數型別...。

這麼多種常數設計方式,我們要如何挑選正確的呢?
以下提出一般常用的原則(記住,只是原則,沒有規定一定要這樣)
1)#define大致上會被丟到歷史的洪流去了,因為本身有很多隱藏的危機,在系統寫大的時候,經常造成不知所謂的BUG
2)const變數,每個物件還有機會設定各自的常數值
class ABC
{
private:
  const float PI;
public:
  ABC(float a)
  :PI(a)
  {
  }
};

void main( void )
{
  ABC abc(100);
  ABC def(200);
}

3)通常用於類別內,獨一無二的非整數的常數值

4)通常用於類別內,獨一無二的整數的常數值

2009年2月4日 星期三

恐怖的巧合?

小澤澤心愛的玩具不見了,雖是他生平第一台小卡車,也被他玩壞得差不多了,但是他對這台車就是情有獨鍾,玩來玩去,還是這台最好玩,那日發現找不到小卡車,被小澤澤玩丟了,他還好,有很多的替代玩具,暫時沒想到還有這台車子,而全部的大人都卯起來找,可是一直沒發現,時間越久大家越擔心,不知道他哪天又開始"不要、不要"的時候,找不到東西給他玩。

這天,老婆心血來潮,當著小澤澤的面前問他,"你的小卡車呢?",小澤澤依照往常"嗯!"地胡亂一指,指著辦公桌下和活動櫃中間,一個隱密狹小的隙縫,老婆低頭一看,真的塞在那裡!! 我和老婆面面相覷,不知道小澤澤是真的懂事了還是運氣好? 不過我希望是前者啦,反正問他真的假的,他也答不出來。

2009年2月2日 星期一

澤澤的歸納法

小澤澤會開始認東西了,牛牛啊、狗狗啊、球球啊,還有,他會說英文的Apple,這實在是令人神奇與感動,只是他現在對事件的分辨還一知半解,經常讓人又覺得好笑,譬如,除了牛牛之外,四隻腳的都是狗狗,圓圓的東西都是Apple而且具有球球的屬性,所以拿水果給他玩要小心,他拿在手裡,第一件事就是用稚嫩的童音,可愛地大喊一聲"丟!",然後水果就摔在地上滾來滾去,看他拍手大笑,大人可是哭笑不得,只是我們要吃摔爛的水果,這時後還真羨慕不吃水果的老婆。