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)通常用於類別內,獨一無二的整數的常數值

沒有留言:

張貼留言