C++編程指向成員的指針以及this指針的基本使用指南
指向成員的指針
指向成員的指針的聲明是指針聲明的特例。使用以下序列來聲明它們:
[storage-class-specifiers] [cv-qualifiers] type-specifiers [ms-modifier] qualified-name ::* [cv-qualifiers] identifier [= & qualified-name :: member-name];
聲明說明符:
- 可選存儲(chǔ)類說明符。
- 可選 const 和/或 volatile 說明符。
- 類型說明符:類型的名稱。這是要指向的成員的類型,而不是類。
聲明符:
- 可選的 Microsoft 專用修飾符。
- 包含要指向的成員的類的限定名。
- :: 運(yùn)算符。
- * 運(yùn)算符。
- 可選 const 和/或 volatile 說明符。
- 命名指向成員的指針的標(biāo)識(shí)符。
可選的初始值設(shè)定項(xiàng):
- = 運(yùn)算符。
- & 運(yùn)算符。
- 類的限定名。
- :: 運(yùn)算符。
- 適當(dāng)類型的類的非靜態(tài)成員的名稱。
像往常一樣,允許在單個(gè)聲明中使用多個(gè)聲明符(以及任何關(guān)聯(lián)的初始值設(shè)定項(xiàng))。
指向類的成員的指針與普通指針不同,因?yàn)樗性摮蓡T的類型的類型信息和該成員所屬的類的類型信息。常規(guī)指針只標(biāo)識(shí)內(nèi)存中的一個(gè)對(duì)象或只具有其地址。指向類的某個(gè)成員的指針標(biāo)識(shí)類的所有實(shí)例中的該成員。以下示例聲明類、Window 和一些指向成員數(shù)據(jù)的指針。
// pointers_to_members1.cpp class Window { public: Window(); // Default constructor. Window( int x1, int y1, // Constructor specifying int x2, int y2 ); // window size. bool SetCaption( const char *szTitle ); // Set window caption. const char *GetCaption(); // Get window caption. char *szWinCaption; // Window caption. }; // Declare a pointer to the data member szWinCaption. char * Window::* pwCaption = &Window::szWinCaption; int main() { }
在前面的示例中,pwCaption 是一個(gè)指針,它指向具有 Windowchar* 類型的類 的任何成員。類型 pwCaption 不是 char * Window::*。下一個(gè)代碼片段將指針聲明為 SetCaption 和 GetCaption 成員函數(shù)。
const char * (Window::*pfnwGC)() = &Window::GetCaption; bool (Window::*pfnwSC)( const char * ) = &Window::SetCaption;
指針 pfnwGC 和 pfnwSC 分別指向 GetCaption 類的 SetCaption 和 Window。以下代碼直接使用指向成員 pwCaption 的指針將信息復(fù)制到窗口標(biāo)題:
Window wMainWindow; Window *pwChildWindow = new Window; char *szUntitled = "Untitled - "; int cUntitledLen = strlen( szUntitled ); strcpy_s( wMainWindow.*pwCaption, cUntitledLen, szUntitled ); (wMainWindow.*pwCaption)[cUntitledLen - 1] = '1'; //same as //wMainWindow.SzWinCaption [cUntitledLen - 1] = '1'; strcpy_s( pwChildWindow->*pwCaption, cUntitledLen, szUntitled ); (pwChildWindow->*pwCaption)[cUntitledLen - 1] = '2'; //same as //pwChildWindow->szWinCaption[cUntitledLen - 1] = '2';
.* 和 –>* 運(yùn)算符(指向成員的指針運(yùn)算符)的區(qū)別在于 .* 運(yùn)算符選擇成員給定的對(duì)象或?qū)ο笠?,?–>* 運(yùn)算符通過指針選擇成員。(有關(guān)這些運(yùn)算符的更多信息,請(qǐng)參閱使用指向成員的指針運(yùn)算符的表達(dá)式。)
指向成員的指針運(yùn)算符的結(jié)果是成員的類型 - 本例中為 char *。
以下代碼片段使用指向成員的指針調(diào)用成員函數(shù) GetCaption 和 SetCaption:
// Allocate a buffer. enum { sizeOfBuffer = 100 }; char szCaptionBase[sizeOfBuffer]; // Copy the main window caption into the buffer // and append " [View 1]". strcpy_s( szCaptionBase, sizeOfBuffer, (wMainWindow.*pfnwGC)() ); strcat_s( szCaptionBase, sizeOfBuffer, " [View 1]" ); // Set the child window's caption. (pwChildWindow->*pfnwSC)( szCaptionBase );
針對(duì)指向成員的指針的限制
靜態(tài)成員的地址不是指向成員的指針。它是指向靜態(tài)成員的一個(gè)實(shí)例的常規(guī)指針。由于給定類的所有對(duì)象只存在一個(gè)靜態(tài)成員實(shí)例,因此可以使用普通的 address-of (&) 和取消引用 (*) 運(yùn)算符。
指向成員和虛函數(shù)的指針
通過指向成員函數(shù)的指針調(diào)用虛函數(shù)就如同直接調(diào)用函數(shù)一樣;將在 v 表中查找并調(diào)用正確的函數(shù)。
一直以來,虛函數(shù)工作的關(guān)鍵是通過指向基類的指針來調(diào)用它們。(有關(guān)虛函數(shù)的詳細(xì)信息,請(qǐng)參閱虛函數(shù)。)
以下代碼演示如何通過指向成員函數(shù)的指針調(diào)用虛函數(shù):
// virtual_functions.cpp // compile with: /EHsc #include <iostream> using namespace std; class Base { public: virtual void Print(); }; void (Base ::* bfnPrint)() = &Base :: Print; void Base :: Print() { cout << "Print function for class Base\n"; } class Derived : public Base { public: void Print(); // Print is still a virtual function. }; void Derived :: Print() { cout << "Print function for class Derived\n"; } int main() { Base *bPtr; Base bObject; Derived dObject; bPtr = &bObject; // Set pointer to address of bObject. (bPtr->*bfnPrint)(); bPtr = &dObject; // Set pointer to address of dObject. (bPtr->*bfnPrint)(); } //Output: Print function for class Base Print function for class Derived
this 指針
this 指針是只能在 class、struct或 union 類型的非靜態(tài)成員函數(shù)中訪問的指針。它指向?yàn)槠湔{(diào)用成員函數(shù)的對(duì)象。靜態(tài)成員函數(shù)沒有 this 指針。
語法
this this->member-identifier
備注
對(duì)象的 this 指針不是對(duì)象的一部分;它沒有在對(duì)象上的 sizeof 語句的結(jié)果中反映。相反,當(dāng)對(duì)某個(gè)對(duì)象調(diào)用非靜態(tài)成員函數(shù)時(shí),該對(duì)象的地址將由編譯器作為隱藏的參數(shù)傳遞給函數(shù)。例如,以下函數(shù)調(diào)用:
myDate.setMonth( 3 );
可以按以下方式解釋:
setMonth( &myDate, 3 );
對(duì)象的地址可從成員函數(shù)的內(nèi)部作為 this 指針提供。 this 的大多數(shù)使用都是隱式的。在引用類的成員時(shí)顯式使用 this 是合法的,但沒有必要。例如:
void Date::setMonth( int mn ) { month = mn; // These three statements this->month = mn; // are equivalent (*this).month = mn; }
表達(dá)式 *this 通常用于從成員函數(shù)返回當(dāng)前對(duì)象:
return *this;
this 指針還用于防止自引用:
if (&Object != this) { // do not execute in cases of self-reference
注意
由于 this 指針無法更改,因此不允許對(duì) this 賦值。C++ 的早期實(shí)現(xiàn)允許對(duì) this 賦值。
this 指針有時(shí)可直接使用 - 例如,當(dāng)操作自引用數(shù)據(jù)結(jié)構(gòu),而其中需要當(dāng)前對(duì)象的地址時(shí)。
// this_pointer.cpp // compile with: /EHsc #include <iostream> #include <string.h> using namespace std; class Buf { public: Buf( char* szBuffer, size_t sizeOfBuffer ); Buf& operator=( const Buf & ); void Display() { cout << buffer << endl; } private: char* buffer; size_t sizeOfBuffer; }; Buf::Buf( char* szBuffer, size_t sizeOfBuffer ) { sizeOfBuffer++; // account for a NULL terminator buffer = new char[ sizeOfBuffer ]; if (buffer) { strcpy_s( buffer, sizeOfBuffer, szBuffer ); sizeOfBuffer = sizeOfBuffer; } } Buf& Buf::operator=( const Buf &otherbuf ) { if( &otherbuf != this ) { if (buffer) delete [] buffer; sizeOfBuffer = strlen( otherbuf.buffer ) + 1; buffer = new char[sizeOfBuffer]; strcpy_s( buffer, sizeOfBuffer, otherbuf.buffer ); } return *this; } int main() { Buf myBuf( "my buffer", 10 ); Buf yourBuf( "your buffer", 12 ); // Display 'my buffer' myBuf.Display(); // assignment opperator myBuf = yourBuf; // Display 'your buffer' myBuf.Display(); }
輸出:
my buffer your buffer
this 指針的類型
通過 const 和 關(guān)鍵字,可以在函數(shù)聲明中修改 volatilethis 指針的類型。若要將函數(shù)聲明為具有一個(gè)或多個(gè)關(guān)鍵字的特性,請(qǐng)將關(guān)鍵字添加到函數(shù)參數(shù)列表的后面。
請(qǐng)看以下示例:
// type_of_this_pointer1.cpp class Point { unsigned X() const; }; int main() { }
上面的代碼聲明一個(gè)成員函數(shù) X,其中,this 指針被視為指向 const 對(duì)象的 const 指針??梢允褂?cv-mod-list 選項(xiàng)的組合,但它們始終通過 this 修改指向的對(duì)象,而不是 this 指針本身。因此,以下聲明將聲明函數(shù) X;this 指針是指向 const 對(duì)象的 const 指針:
// type_of_this_pointer2.cpp class Point { unsigned X() const; }; int main() { }
成員函數(shù)中 this 指針的類型由以下語法描述,其中,cv-qualifier-list 是從成員函數(shù)聲明符中確定的,可以是 const 和/或 volatile,而 class-type 是類的名稱:
[cv-qualifier-list] class-type * const this
換言之,this 始終是 const 指針;無法重新指派它。成員函數(shù)聲明中使用的 const 或 volatile 限定符適用于由該函數(shù)范圍中的 this 指向的類實(shí)例。
下表介紹了有關(guān)這些修飾符的工作方式的更多信息。
this 修飾符的語義
修飾符 | |
---|---|
const | 不能更改數(shù)據(jù)成員;無法調(diào)用不是 const 的成員函數(shù)。 |
volatile | 每次訪問成員數(shù)據(jù)時(shí),都會(huì)從內(nèi)存中加載該數(shù)據(jù);禁用某些優(yōu)化。 |
將 const 對(duì)象傳遞給不是 const 的成員函數(shù)是錯(cuò)誤的。同樣,將 volatile 對(duì)象傳遞給不是 volatile 的成員函數(shù)也是錯(cuò)誤的。
聲明為 const 的成員函數(shù)不能更改數(shù)據(jù)成員 - 在此類函數(shù)中,this 指針是指向 const 對(duì)象的指針。
注意
構(gòu)造函數(shù)和析構(gòu)函數(shù)不能聲明為 const 或 volatile。但是,可以在 const 或 volatile 對(duì)象上調(diào)用它們。
相關(guān)文章
C++實(shí)現(xiàn)統(tǒng)計(jì)代碼運(yùn)行時(shí)間的示例詳解
這篇文章主要為大家詳細(xì)介紹了C++一個(gè)有趣的小項(xiàng)目——統(tǒng)計(jì)代碼運(yùn)行時(shí)間,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-05-05構(gòu)造函數(shù)不能聲明為虛函數(shù)的原因及分析
構(gòu)造函數(shù)不需要是虛函數(shù),也不允許是虛函數(shù),因?yàn)閯?chuàng)建一個(gè)對(duì)象時(shí)我們總是要明確指定對(duì)象的類型,盡管我們可能通過實(shí)驗(yàn)室的基類的指針或引用去訪問它但析構(gòu)卻不一定,我們往往通過基類的指針來銷毀對(duì)象2013-10-10C++實(shí)現(xiàn)高校教室管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)高校教室管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03