一摇肌、const
考慮問題:下面程序中數(shù)字 10
的含義?
for (int i = 0; i != 10; ++i){
//...
}
顯然從程序來看仪际,我們并不知道
10
是怎樣一個存在围小,因此它也被稱為 魔數(shù)(magic number),意思是這個數(shù)的意義不能從上下文體現(xiàn)出來树碱,就像魔術(shù)一樣憑空出現(xiàn)了肯适。或者如果這個程序多次使用數(shù)字
10
的話,當(dāng)需要要把10
改為20
的話就麻煩了成榜。
一種簡單的解決辦法是
int max = 10;
for (int i = 0; i != max; ++i){
//...
}
這樣不僅可讀性好很多框舔,而且修改起來也相當(dāng)方便。
max
是可以被修改的
1.1赎婚、定義const對象
上面到刘绣,max
可能會被有意或無意的修改,在某些情況下這很嚴(yán)重挣输。const 提供一種解決辦法
const int max = 10纬凤;
此時定義 max
為 常量 并初始化為 10,但此時的 max
不可被修改歧焦。
C++中的 const 跟 Java 中的 final 或 PHP 中的 define 類似移斩。
const 定義的常量不可修改肚医,所以定義時必須初始化:
const std:string hi = "Hello";//正確
const int i; //錯誤
1.2绢馍、const對象默認(rèn)為文件的局部變量
跟普通的變量不一樣向瓷,const定義的變量需要特別的說明才可以在其他文件中訪問。例如
-
普通變量
//file1.cpp int max = 10; //定義變量 //file2.cpp extern int max; //聲明外部變量 //下面可以使用變量 max
-
const變量
//file1.cpp extern const int max = 10; //定義變量 //file2.cpp extern const int max; //聲明外部變量 //下面可以使用const變量 max
定義非
const
變量時默認(rèn)問extern
舰涌。而cost
變量必須顯式的指定它為extern
才可以被其他文件訪問猖任。
二、引用
引用(reference)就是對象的另一個名字瓷耙。在實際程序中朱躺,引用主要作為函數(shù)的形參,形參的內(nèi)容將在后續(xù)介紹搁痛。
引用是一種 復(fù)合類型(compound type)长搀,在變量名前加 &
符號來定義。復(fù)合類型是指用其他類型定義的類型鸡典。每個引用都關(guān)聯(lián)到其他某一類型源请,不能定義引用的引用,但可以定義任意類型的引用彻况,并且可以有多個引用谁尸。下面用例子說明
int val = 1;
int &reVal1 = val; //正確
int &reVal2 = val; //正確:val的第二個別名
int &reVal3; //錯誤:引用必須初始化
int &reVal4 = 1; //錯誤:引用必須使用對象初始化
2.1、引用是別名
引用只是它所綁定對象的另一個名字纽甘,在引用上做的所有操作實際上都作用在原對象上:
reVal1 = 5良蛮; //相當(dāng)于:val = 5;
reVal1 += 1; //相當(dāng)于:val += 1;
int val2 = reVal1; //相當(dāng)于:int val2 = val;
下面程序的結(jié)果更能直觀的說明這個問題
int main()
{
int val = 0;
int &reVal1 = val;
int &reVal2 = val;
std::cout << "val = " << val << ", reVal1 = "<< reVal1 << ", reVal2 = " << reVal2 << std::endl;
reVal1 = 1; //對 reVal1 操作
std::cout << "val = " << val << ", reVal1 = "<< reVal1 << ", reVal2 = " << reVal2 << std::endl;
reVal2 = 2; //對 reVal2 操作
std::cout << "val = " << val << ", reVal1 = "<< reVal1 << ", reVal2 = " << reVal2 << std::endl;
return 0;
}
運行結(jié)果是:
val = 0, reVal1 = 0, reVal2 = 0
val = 1, reVal1 = 1, reVal2 = 1
val = 2, reVal1 = 2, reVal2 = 2
2.2悍赢、const引用
非 const 不能引用 const决瞳,只有 const 能夠引用 const,且 const 引用不能修改:
int i = 0;
const int val = 0; //正確:0是右值
const int &reVal1 = val; //正確:val是左值
const int &reVal2 = i; //正確
reVal1 = 1; //錯誤:const 引用是只讀的
int &reVal3 = val; //錯誤:非 const 不能引用 const
跟非 const 不同之處還有:
int i = 0;
const int &re1 = 1; //正確
const int &re2 = re1 + i; //正確
對于下面這種綁定到同一類型的情況:
int i = 0;
const int &re1 = i; //此時 re1 = 0左权;
i = 1; //此時 re1 = 1瞒斩;
當(dāng)改變 i
時,re1
也會被改變涮总。
還有另一種情況:綁定到不同類型的值
double i = 1.1;
const int &re1 = i; //此時 re1 = 1胸囱;
i = 2.1; //此時 re1 = 1;
因為對于這種情況瀑梗,編譯器會解釋為:
int temp = i;
const int &re1 = temp;
所以烹笔,改變 i
實際上改變的是 temp
, re1
不受影響抛丽。
const 引用可以綁定左值或右值谤职,非 const 引用只能綁定左值。
三亿鲜、typedef
typedef 跟引用有點類似允蜈,不過 typedef 是定義類型的別名:
typedef double wages; //wages 是 double 的別名
typedef int score; //score 是 int 的別名
typedef wages salary; //salary 是 double 的別名
其作用是:
- 為了隱藏特定的類型冤吨,強調(diào)使用類型的目的;
- 簡化復(fù)雜的類型定義饶套,易于理解漩蟆;
- 允許一個類型用于多個目的,并且每次使用時目的明確妓蛮;
四怠李、枚舉
如果要為某屬定義一組可選擇的值,每個只對應(yīng)一種狀態(tài)蛤克,比如文件的打開狀態(tài):輸出捺癞,輸入和追加分別對應(yīng) 0,1,2。則有可能會這樣定義:
const int input = 0构挤;
const int output = 1髓介;
const int append = 2;
屬性選擇很多時這樣定義就不方便筋现,枚舉(enumeration) 是一種替代方法唐础。
4.1、定義和初始化枚舉
枚舉的關(guān)鍵字是 enum
夫否,定義如下
enum open_modes {input, output, append};
默認(rèn)地彻犁,第一個枚舉成員賦值為 0,后面的依次加 1凰慈。
4.2汞幢、枚舉成員是常量
可以為一個或多個成員提供初值,初始化枚舉成員的值必須是一個 常量表達(dá)式(constant expression)微谓,整型字面值也是常量表達(dá)式森篷。
// sphere = 2, polygon = 2
enum forms {shape = 1, sphere, cylinder = 1, polygon}
4.3、每個enum都定義了一種唯一的類型
forms f1 = shape; //正確:shape 是 forms 類型的枚舉成員
forms f2 = square; //錯誤:square 不是 forms 類型豺型;
forms f3 = 1仲智; //錯誤:1 是 int類型,不是forms類型
即使 1 與 shape 相關(guān)聯(lián)姻氨,但是 1 賦值給 f3 還是非法的
五钓辆、類類型
在C++中可以通過定義 類(class) 來自定義數(shù)據(jù)類型。類定義了該類型的對象包含的數(shù)據(jù)和該類型對象可以執(zhí)行的操作肴焊。標(biāo)準(zhǔn)庫類型 string前联、istream、ostream都定義成類娶眷,關(guān)于類后續(xù)詳細(xì)介紹似嗤。
本節(jié)繼續(xù)使用在 讀《C++primer》day1:快速入門 的第三部分提到的 Sales_item 類舉例。
5.1届宠、從操作開始設(shè)計類
每個類都定義了一個 接口(interface) 和一個 實現(xiàn)(implementation)烁落。接口由使用該類的代碼需要執(zhí)行組成乘粒,實現(xiàn)一般包括該類所需的數(shù)據(jù)及操作。
定義類時伤塌,通常先定義接口灯萍,即該類所提供的操作。以 Sales_item 舉例:
- 加法
+
:將兩個對象相加寸谜; - 輸入
>>
: 讀取一個對象竟稳; - 輸出
<<
:輸出一個對象属桦; - 賦值
=
:將一個對象賦給另一個對象熊痴; - 對比
?
:對比兩個對象是否屬于同一本書(函數(shù)same_isbn);
雖然現(xiàn)在我們并不能實現(xiàn)這些操作(需要更多的知識)聂宾,但可以考慮實現(xiàn)這些操作需要什么樣的數(shù)據(jù):
- 記錄各書本的銷售冊數(shù)果善;
- 該書的總銷售收入;
- 計算該書的平均售價系谐;
大概就可以知道需要一個 unsigned
類型對象來記錄數(shù)的銷售冊數(shù)巾陕,一個 double
類型對象計入總收入,string
類型對象記錄書本的ISBN纪他。
5.2鄙煤、定義Sales_item類
按上一節(jié)提到的操作和數(shù)據(jù),可以這樣定義:
class Sales_item {
public:
//各種操作在此定義
private:
std:string isbn;
unsigned units_sold;
double revenue;
};
類定義以關(guān)鍵字 class 開始茶袒,后面是該類的類名梯刚,類體位于花括號內(nèi)部,花括號后面必須要跟一個分號薪寓。
新手經(jīng)常會忘記類定義后面的分號亡资!
類體可以為空,類體定義了該類型的數(shù)據(jù)和操作向叉。這些數(shù)據(jù)和操作也稱為 成員(member)锥腻,數(shù)據(jù)稱為 數(shù)據(jù)成員(data member),操作稱為 成員函數(shù)母谎。
類定義可以包含多個 private 和 public 訪問標(biāo)號(access label)瘦黑,給定的訪問標(biāo)號作用域到下一個訪問標(biāo)號出現(xiàn)時為止。類中 public 部分定義的成員在程序的任何部分都可以訪問奇唤,不是類的組成部分的代碼不能方便問 private 成員幸斥,這樣可以保證Sales_item對象不能直接操縱數(shù)據(jù)成員。
5.3冻记、使用struct關(guān)鍵字
struct 關(guān)鍵字也可以定義類類型睡毒,它是從 C 語言繼承而來。區(qū)別
- 用關(guān)鍵字
class
定義類:定義在第一個標(biāo)號之前的所有成員都默認(rèn)為private冗栗; - 用關(guān)鍵字
struct
定義類:定義在第一個標(biāo)號之前的所有成員都默認(rèn)為public演顾;
用 struct
重新定義前面的Sales_item類:
class Sales_item {
//不需要 public 訪問標(biāo)號
private:
std:string isbn;
unsigned units_sold;
double revenue;
};
用 class 和 struct 關(guān)鍵字定義類的唯一區(qū)別就在于 默認(rèn)訪問級別供搀。默認(rèn)情況下,struct 的成員為 public钠至,而 class 的成員的是 private葛虐。
END.