第8章 常量

2022-08-13 12:57:16 字數 4464 閱讀 9816

值替代

當用c語言進行程式設計時,預處理器可以不受限制地建立巨集並用它來替代值。因為預處理器只做些文字替代,它既沒有型別檢查概念,也沒有型別檢查功能,所以預處理器的值替代會產生一些微小的問題,這些問題在

c++中可以通過使用

const

值而避免。

比如:

#define buffersize 100

buffersize是乙個名字,它只是在預處理期間存在,因此它不占用儲存空間且能放在乙個標頭檔案裡,目的是為使用它的所有編譯單元提供乙個值。使用值替代而不是使用所謂的「不可思議的數」,這對於支援**維護是非常重要的。

標頭檔案裡的const

要使用const

而非#define

,同樣必須把

const

定義放進標頭檔案裡。這樣通過包含標頭檔案,可把

const

定義單獨放在乙個地方並把它分配給乙個編譯單元。

c++中的

const

預設為內部連線,也就是說,

const

僅在const

被定義過的檔案裡才是可見的,而在連線時不能被其他編譯單元看到。

可以參考:

const可以用於陣列,但必須保證編譯器不會複雜到把乙個陣列儲存到它的符號表中,所以必須分配記憶體。在這種情況下,

const

意味著「不能改變的一塊儲存空間」。然而,不能在編譯期間使用它的值,因為編譯器在編譯期間不需要知道儲存的內容。這樣,就能明白下面的**是非法的:

const

int i = ;

float f[i[3]]; //

illegal

在乙個陣列定義裡,編譯器必須能產生這樣的**,它們移動棧指標來儲存陣列。在上面的非法定義裡,它不能在陣列定義裡找到乙個常數表示式。

與c語言的區別

c中const

的意思是「乙個不能被改變的普通變數」,

const

常量總是占用儲存而且它的名字是全域性的。這樣,

c編譯器不能把

const

看成乙個編譯期間的常量。在

c中,如果寫:

const

int bufsize = 100

;

char buf[bufsize];

儘管看起來好像做了一件合理的事,但這將得出乙個錯誤。因為bufsize

占用某塊記憶體,所以

c編譯器不知道它在編譯時的值。在

c語言中可以選擇這樣書寫:

const

int bufzie;

這樣寫在c++

中是不對的,而

c編譯器則把它作為乙個宣告,指明在別的地方有儲存分配。因為c預設

const

是外部連線的,所以這樣做是合理的。

c++預設

const

是內部連線的,這樣如果在

c++中想完成與

c中同樣的事情,必須用

extern

明確地把連線改為外部連線:

extern

const

int bufsize; //

declaration only

在c中使用限定符

const

不是很有用的,

c總是迫使程式設計師在預處理器裡使用

#define。指標

當使用帶有指標的const

時,有兩種選擇:

const

修飾指標指向的內容,或者

const

修飾在指標裡儲存的位址(即修飾的是變數)。

指向const

內容的指標

const修飾「最靠近」它的那個。這樣,如果要使正指向的元素不發生改變,得寫乙個像這樣的定義:

const

int *u;

從識別符號開始,是這樣讀的:u

是乙個指標,它指向乙個

const int

。這裡不需要初始化,因為

u可以指向任何識別符號(也就是說變數

u不是乙個

const

),但它所指的值是不能改變的。

int

const *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

時,那麼這個函式的返回值不能是乙個左值(即它不能被賦值,也不能被修改),如:

class

x ;

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

沒有意義的原因是:編譯器已經不讓它成為乙個左值(因為它總是乙個值而不是乙個變數)。僅當按值返回使用者定義的型別物件時,才會出現上述問題。

傳遞和返回位址

const

int *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

成員函式,但仍然想在物件裡改變某些資料,這時該怎麼辦呢?下面是乙個例子:

class

y ;

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...