值替代
當用c語言進行程式設計時,預處理器可以不受限制地建立巨集並用它來替代值。因為預處理器只做些文字替代,它既沒有型別檢查概念,也沒有型別檢查功能,所以預處理器的值替代會產生一些微小的問題,這些問題在
c++中可以通過使用
const
值而避免。
比如:
#define buffersize 100
buffersize是乙個名字,它只是在預處理期間存在,因此它不占用儲存空間且能放在乙個標頭檔案裡,目的是為使用它的所有編譯單元提供乙個值。使用值替代而不是使用所謂的「不可思議的數」,這對於支援**維護是非常重要的。
標頭檔案裡的const
要使用const
而非#define
,同樣必須把
const
定義放進標頭檔案裡。這樣通過包含標頭檔案,可把
const
定義單獨放在乙個地方並把它分配給乙個編譯單元。
c++中的
const
預設為內部連線,也就是說,
const
僅在const
被定義過的檔案裡才是可見的,而在連線時不能被其他編譯單元看到。
可以參考:
const可以用於陣列,但必須保證編譯器不會複雜到把乙個陣列儲存到它的符號表中,所以必須分配記憶體。在這種情況下,
const
意味著「不能改變的一塊儲存空間」。然而,不能在編譯期間使用它的值,因為編譯器在編譯期間不需要知道儲存的內容。這樣,就能明白下面的**是非法的:
constint i = ;
float f[i[3]]; //
illegal
在乙個陣列定義裡,編譯器必須能產生這樣的**,它們移動棧指標來儲存陣列。在上面的非法定義裡,它不能在陣列定義裡找到乙個常數表示式。
與c語言的區別
c中const
的意思是「乙個不能被改變的普通變數」,
const
常量總是占用儲存而且它的名字是全域性的。這樣,
c編譯器不能把
const
看成乙個編譯期間的常量。在
c中,如果寫:
constint bufsize = 100
;
char buf[bufsize];
儘管看起來好像做了一件合理的事,但這將得出乙個錯誤。因為bufsize
占用某塊記憶體,所以
c編譯器不知道它在編譯時的值。在
c語言中可以選擇這樣書寫:
constint bufzie;
這樣寫在c++
中是不對的,而
c編譯器則把它作為乙個宣告,指明在別的地方有儲存分配。因為c預設
const
是外部連線的,所以這樣做是合理的。
c++預設
const
是內部連線的,這樣如果在
c++中想完成與
c中同樣的事情,必須用
extern
明確地把連線改為外部連線:
externconst
int bufsize; //
declaration only
在c中使用限定符
const
不是很有用的,
c總是迫使程式設計師在預處理器裡使用
#define。指標
當使用帶有指標的const
時,有兩種選擇:
const
修飾指標指向的內容,或者
const
修飾在指標裡儲存的位址(即修飾的是變數)。
指向const
內容的指標
const修飾「最靠近」它的那個。這樣,如果要使正指向的元素不發生改變,得寫乙個像這樣的定義:
constint *u;
從識別符號開始,是這樣讀的:u
是乙個指標,它指向乙個
const int
。這裡不需要初始化,因為
u可以指向任何識別符號(也就是說變數
u不是乙個
const
),但它所指的值是不能改變的。
intconst *v;
並非所有的人都很肯定地認為:應該讀成,「v
是乙個指向
int的
const
指標」。然而,實際應讀成「
v是乙個指向恰好是
const
的int
的普通指標」,效果與前面定義的一樣。為使程式更具有可讀性,應該堅持用第一種形式。
const指標變數
使指標本身成為乙個const
指標,必須把
const
標明的部分放在
*的右邊,如:
int d = 1;
int *const w = &d;
現在它讀成「w
是乙個指標,這個指標是指向
int的
const
指標」。因為指標本身現在是
const
指標,編譯器要求給它乙個初始值,這個值在指標生命週期內不變。然而要改變它所指向的值是可以的,可以寫:
*w = 2;
字元陣列的字面值
有人可以寫:
char *cp = 「howdy」;
編譯器將接受它而不報告錯誤。從技術上講,這是乙個錯誤,因為字元陣列的字面值(在這裡是」howdy」)是被編譯器作為乙個常量字元陣列建立的,所引用該字元陣列得到的結果是它在記憶體裡的首位址。修改該字元陣列的任何字元都會導致執行時錯誤。
如果要修改字串,就要把它放在乙個陣列中:
char cp = 「howdy」;
函式引數和返回值
返回const值
對於內部型別來說,按值返回的是否是乙個const
,是無關緊要的,所以按值返回乙個內部型別時,應該去掉
const
,從而不使客戶程式設計師混淆。
當處理使用者定義的型別時,按值返回常量是很重要的。如果乙個函式按值返回乙個類物件為const
時,那麼這個函式的返回值不能是乙個左值(即它不能被賦值,也不能被修改),如:
classx ;
x::x(
int ii)
void x::modify()
x f5()
const
x f6()
void f7(x &x)
intmain()
f5()返回乙個非
const x
物件,然而
f6()
返回乙個
const x
物件。僅僅是非
const
返回值能作為乙個左值使用,因此,當按值返回乙個物件時,如果不讓這個物件作為乙個左值使用,則使用
const
很重要。
當按值返回乙個內部型別時,const
沒有意義的原因是:編譯器已經不讓它成為乙個左值(因為它總是乙個值而不是乙個變數)。僅當按值返回使用者定義的型別物件時,才會出現上述問題。
傳遞和返回位址
constint *const
w()
int *ip2 = w(); //
not ok
const
int *const ccip = w(); //
okconst
int *cip2 = w(); //
ok
編譯器拒絕把函式w()
的返回值賦給乙個非
const
指標,而接受乙個
const int* const
,但令人奇怪的是它也接受乙個
const int *
類const物件只能呼叫
const
成員函式。
const成員函式可以被
const
物件和非
const
物件呼叫。不修改資料成員的任何函式都應該把它們宣告為
const
,這樣它可以和
const
物件一起使用。
可變的:按位const
和按邏輯
const
如果想要建立乙個const
成員函式,但仍然想在物件裡改變某些資料,這時該怎麼辦呢?下面是乙個例子:
classy ;
y::y()
void y::f() const
intmain()
這種方法是可行的,在過去的程式**裡可以看到這種用法,但這不是首選的技術。應當在類宣告裡使用關鍵字mutable
,以指定乙個特定的資料成員可以在乙個
const
物件裡被改變。
第8章指標
1.指標 指標是儲存記憶體位址的變數。在記憶體中每一塊儲存單元都有相對應的唯一的位址編號,指標就是一塊儲存這種編號的空間 2.對於乙個變數可以用 符號來獲取它的位址 int a int p a 什麼樣的變數,就需要宣告對應的型別的指標。這是為了告訴系統,我從這個位址開始要讀取多少位的記憶體塊,才能正...
第8章 多型
執行時的多型 我們所說的多型一般是執行時的多型。要使用多型,在宣告物件時就應該遵循一條法則 宣告的總是父類型別或介面型別,建立的是實際型別。物件導向的三大特徵 封裝 繼承 多型多型通過分離 做什麼 和 怎麼做 從另外的乙個角度將介面和實現分離開來。封裝通過合併特徵和行為來建立新的資料型別。實現隱藏 ...
第8章 函式
位置實參,關鍵字是參 預設值,注意順序,把已經有預設值的放在最後 topping這個可以接收任何實參,一般放形參最後,它是個空元組,當作列表一樣就行 def pet name,size 27 預設值 print name size n input please get me a name s inp...