C++程式設計常見錯誤之-類中的常量
1.const與#define的比較
兩點:
1.cosnt常量有資料型別,而巨集常量沒有資料型別,編譯器可以對前者進行靜態資料型別安全檢查,而對後者只進行字元替換,沒有安全檢查,並且會在字元替換時可能會產生意料不到的錯誤(邊際效應)。
2.有些整合化的除錯工具可以對const常量進行除錯,但是不對巨集常量進行除錯。
2.類中的常量
2.1錯誤用法:
//類中的常量
class A
{
public:
const int SIZE = 100; //注意,並非期望的全域性常量,因為每個類都會會有這樣一個常量
int array[SIZE]; //錯誤,未知的SIZE,因為在類的物件被建立之前,編譯器無法知道SIZE的值是什麼
};
2.2常量正確用法一 類中列舉常量
class A
{
public:
enum
{
SIZE1 = 100, //列舉常量
SIZE2 = 200
};
int array1[SIZE1];
int array2[SIZE2];
};
提示:列舉常量不會佔用物件的儲存空間,它在編譯時會被全部求值,更何況它定義的是一個匿名列舉型別。
列舉型別的缺點是:不能表示浮點數(如PI=3.14159)和字串。
2.3常量正確用法二 static const
class A
{
public:
static const int SIZE1 = 100; //列舉常量
static const int SIZE2 = 200;
int array1[SIZE1];
int array2[SIZE2];
};
提示:有的編譯器可能會要求必須在類外初始化靜態資料成員。
另外3.1
,在C和C++中定義常量是有區別的。
在C程式中const符號常量定義的預設連線型別(Linkage)是extern的,即外連結(extern Linkage)就像全域性變數一樣。如果在原始檔中定義定義,除非明確改變它的連線型別為內連線,否則其他編譯單元就可以通過extern宣告來訪問它。
但是在C++程式中,const 符號常量定義的預設連線型別卻是static的,即內連線。
3.2
什麼常量最浪費空間呢?答案是字串常量,尤其是較長的字串常量。
所以我們常常這樣定義它們:
const char* const NO_MEMORY="There is no enough memory!";
常量可以在標頭檔案中定義和初始化,也可以在原始檔中定義並初始化,但是兩者差別較大:
①如果在標頭檔案中定義並初始化,那麼包含了標頭檔案的每一個編譯單元不僅會為每一個常量指標常量建立一個單獨的拷貝項,而且也會為長長的字串常量建立一個獨立的拷貝項,就相當於在每一個編譯單元內分別定義和初始化每一個常量一次。
②如果在標頭檔案中宣告所有常量指標常量,而在原始檔中定義並初始化它們,則每一個包含該標頭檔案的編譯單元訪問的不僅是常量指標常量的唯一實體,而且字串常量常量也是唯一實體,這樣就大大節省了記憶體,而且不影響效率。