在C++中,指標用得比較多,對於裡面眾多的指標用法,不免弄得有些糊塗,自從我從圖書館裡借到一本譚浩強教授主編的《C++物件導向程式設計》後,才幫我理清了思路。現把部分內容展現給大家,希望對大家有所協助。
C++程式設計重要基礎就是類和對象,對象指標是很重要的一部分,包括指向對象的指標、指向對象成員的指標、this指標、指向對象的常指標、指向常對象的指標等。
1、指向對象的指標
定義:對象空間的起始地址就是對象的指標。
說明:在建立對象時,編譯系統就為每個對象分配一定的儲存空間以存放其成員,不過注意,在一般情況下不同對象的資料存放區單元中存放的資料成員是不相同,而不同對象的函數代碼卻是相同的,也就是說,它們的函數代碼是共用的。這時我們可以定義一個指標變數用來存放對象的指標。
定義指向類對象的指標變數的一般形式是:
類名 *對象指標名;
如對於與個Time類對象,我們可以有:
Time t;
Time *p;
p=&t;
我們就可以通過對象指標訪問對象和對象的成員,假如所定義的類中有資料成員hour、minute、sec,成員函數有gettime(),則
(*p).hour 即為p指向對象中的hour成員,相當於t.hour
(*p).gettime() 即為p指向對象中的成員函數gettime(),相當於t.gettime()
也可以用如下形式:
p->hour 和 p->gettime()和上面是等價的。
2、指向對象成員的指標
(1)指向對象資料成員的指標
在C中我們學過指向普通變數的指標變數,在C++中定義指向對象資料成員的指標變數的方法和定義指向普通變數的指標變數方法相同,其一般形式為:
資料類型名 *指標變數名;
如:
int *p;
p=&t.hour; //將對象t的資料成員hour的地址賦給p,p指向t.hour
(2)指向對象成員函數的指標
定義指向對象成員函數的指標變數和定義指向普通函數的指標變數不同。
在定義指向普通函數的指標變數時我們可以這樣定義:
void (*p)();
p=fun;
(*p)(); //調用fun函數
然而編譯系統要求在將函數地址賦給指標變數時必須滿足三個條件:
函數參數類型及個數要匹配
函數傳回值的類型要匹配
所屬的類要匹配
顯然在上面的p與類是無關的。為了滿足第三條,我們可以為指標指定類,故定義指向對象成員函數的指標變數一般形式為:
資料類型(類名::*指標變數名)(參數表列);
可以讓指標指向公用的成員函數,如:
void (Time::*p)(); //定義指向Time類對象成員函數的指標變數p
p=&Time::gettime; //把Time類的公用成員函數gettime()地址賦給指標變數p
(t.*p)(); //調用Time類對象t的成員函數gettime()
注意:因為成員函數不存放在對象空間中,多個同類對象共用此成員函數代碼,所以在將成員函數的入口地址賦給指標變數是應寫成:
指向對象成員函數的指標變數=&類名::成員函數名;
在成員函數名後面沒有"()",如果寫成p=&Time::gettime()是錯誤的。[nextp
3、this指標
在每個成員函數中都包含了一個特殊的指標,稱為this,它是指向本類對象的指標,它的值是當前被調用成員函數所在對象的起始地址。之所以有這個指標,是因為為了保證同類的不同對象的成員函數引用的是指定對象中的資料成員,它是系統自動實現的。
如定義一個求體積的函數
int box::vol()
{return(height*width*length);}
假如已經定義了對象t,當調用成員函數t.vol()時,編譯系統就把對象t的起始地址賦給this指標,於是在成員函數引用資料成員時,根據指標this就可以引用到對象t的資料成員。所以C++把上面的函數處理成
int box::vol()
{return(this->height*this->width*this->length);}
由於this的值是當前被調用成員函數所在對象的起始地址,所以可以寫成
int box::vol()
{return((*this).height*(*this).width*(*this).length);}
所以在調用成員函數t.vlo()時,實際的調用方式為t.vol(&t),不過對象t的地址傳給this指標是由系統自動完成的,不需人為加上。
4、指向對象的常指標
將指向對象的指標變數聲明為const型且進行處始化,這樣指標值始終保持為其初值,不能改變其指向。
如:
Time t1(8,8,8),t2;
Time *const p=&t1; //常指標p指向對象t1
p=&t2; //試圖改變p的指向,非法
由上面我們可以看出定義指向對象的常指標的一般形式為:
類名 *const 指標變數名=對象的起始地址;
注意:指向對象的常指標變數的值不能改變,但可以改變它所指向對象中的資料成員的值。
常指標一般用作函數的參數,這樣就不允許在函數執行過程中改變指標變數的值,使其始終保持指向原來的對象。
5、指向常對象的指標變數
首先回顧一下指向常變數的指標變數,其一般形式為:
const 類型名 *指標變數名;
如:
const char *p;
如果一個變數已經被聲明為常變數,那麼只能用指向常變數的指標變數去指向它,而不能用一般的指標變數。另外,指向常變數的指標變數除了可以指向常變數外,還可以指向未被聲明為const的變數,但也不能通過該指標改變其值。例如:
char c='a' //定義字元變數c,未聲名為const
const char *p; //定義指向常變數的指標變數p
p=&c; //p指向字元變數c
*p='b'; //非法
c='b'; //合法
說明:上例中,指標變數p指向字元變數c,並不說把c也聲明成常變數,而只是說在通過指標變數引用c時,c具有常變數的特徵,其值是不能改變的,但c仍然是一個普通變數。
在指向常變數的指標中,關於函數形參的指標類型有幾點值得注意:
如果函數形參是非const型指標變數,實參只能用指向非const型指標;如果函數形參是指向const型變數的指標,實參則可以是const型的或非const型的指標變數。換句話說就是指向常變數的指標可以指向const和非const型的變數,而指向非const型變數的指標只能指向非const的變數。
用指標變數作形參時形參和實參的對應關係表
形參 |
實參 |
合法與否 |
改變指標所指對象的值 |
指向非const型變數的指標 |
非const變數的地址 |
合法 |
行 |
指向非const型變數的指標 |
const變數的地址 |
非法 |
/ |
指向const型變數的指標 |
const變數的地址 |
合法 |
不行 |
指向const型變數的指標 |
非const變數的地址 |
合法 |
不行 |
下面說到正題,指向常對象的指標變數和指向常變數指標變數類似。
如果一個對象已經被聲明為長對象,只能用指向常對象的指標變數指向它,而不能用一般的指標變數指向它。
如果定義了一個指向常對象的指標變數且使它指向一個非const的對象,其指向的對象不能通過指標來改變。
如果定義了一個指向常對象的指標變數,是不能通過它改變所指向的對象的值的,但是指標變數本身的值是可以改變的。
如:
Time t1(8,8,8),t2; //定義對象
const time *p=&t1; //定義指向常對象的指標p,並使它指向t1
p=&t2; //合法,指標p指向對象t2
所以當我們希望在調用函數時對象的值不被修改,我們就可以把形參定義為const型的指標變數,同時用對象的地址作實參(對象可以是const或非const型);當要求對象不僅在調用函數中不被改變,而且在程式執行過程中也不發生改變,我們就把它定義為const型。所以指向常對象的指標最常用於函數的參數,以保護形參指標所指向的對象在函數執行過程中不被修改。
以上是我學習C++指標時的記錄,也是對C++指標用法的總結,我想對大家學習C++應該是很有協助的。