C++編程指向成員的指針以及this指針的基本使用指南
指向成員的指針
指向成員的指針的聲明是指針聲明的特例。使用以下序列來(lái)聲明它們:
[storage-class-specifiers] [cv-qualifiers] type-specifiers [ms-modifier] qualified-name ::* [cv-qualifiers] identifier [= & qualified-name :: member-name];
聲明說(shuō)明符:
- 可選存儲(chǔ)類說(shuō)明符。
- 可選 const 和/或 volatile 說(shuō)明符。
- 類型說(shuō)明符:類型的名稱。這是要指向的成員的類型,而不是類。
聲明符:
- 可選的 Microsoft 專用修飾符。
- 包含要指向的成員的類的限定名。
- :: 運(yùn)算符。
- * 運(yùn)算符。
- 可選 const 和/或 volatile 說(shuō)明符。
- 命名指向成員的指針的標(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ò)指針選擇成員。(有關(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ù)的指針
通過(guò)指向成員函數(shù)的指針調(diào)用虛函數(shù)就如同直接調(diào)用函數(shù)一樣;將在 v 表中查找并調(diào)用正確的函數(shù)。
一直以來(lái),虛函數(shù)工作的關(guān)鍵是通過(guò)指向基類的指針來(lái)調(diào)用它們。(有關(guān)虛函數(shù)的詳細(xì)信息,請(qǐng)參閱虛函數(shù)。)
以下代碼演示如何通過(guò)指向成員函數(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ù)中訪問(wèn)的指針。它指向?yàn)槠湔{(diào)用成員函數(shù)的對(duì)象。靜態(tài)成員函數(shù)沒有 this 指針。
語(yǔ)法
this this->member-identifier
備注
對(duì)象的 this 指針不是對(duì)象的一部分;它沒有在對(duì)象上的 sizeof 語(yǔ)句的結(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 指針無(wú)法更改,因此不允許對(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 指針的類型
通過(guò) 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)的組合,但它們始終通過(guò) this 修改指向的對(duì)象,而不是 this 指針本身。因此,以下聲明將聲明函數(shù) X;this 指針是指向 const 對(duì)象的 const 指針:
// type_of_this_pointer2.cpp
class Point
{
unsigned X() const;
};
int main()
{
}
成員函數(shù)中 this 指針的類型由以下語(yǔ)法描述,其中,cv-qualifier-list 是從成員函數(shù)聲明符中確定的,可以是 const 和/或 volatile,而 class-type 是類的名稱:
[cv-qualifier-list] class-type * const this
換言之,this 始終是 const 指針;無(wú)法重新指派它。成員函數(shù)聲明中使用的 const 或 volatile 限定符適用于由該函數(shù)范圍中的 this 指向的類實(shí)例。
下表介紹了有關(guān)這些修飾符的工作方式的更多信息。
this 修飾符的語(yǔ)義
| 修飾符 | |
|---|---|
| const | 不能更改數(shù)據(jù)成員;無(wú)法調(diào)用不是 const 的成員函數(shù)。 |
| volatile | 每次訪問(wèn)成員數(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++的STL中accumulate函數(shù)的使用方法
這篇文章主要介紹了C++的STL中accumulate的使用方法,accumulate作用是累加求和即自定義類型數(shù)據(jù)處理,下文具體的操作方法需要的小伙伴可以參考一下2022-03-03
詳解c++ atomic原子編程中的Memory Order
在多核編程中,我們使用內(nèi)核對(duì)象【如:事件對(duì)象(Event)、互斥量對(duì)象(Mutex,或互斥體對(duì)象)、信號(hào)量對(duì)象(Semaphore)等】來(lái)避免多個(gè)線程修改同一個(gè)數(shù)據(jù)時(shí)產(chǎn)生的競(jìng)爭(zhēng)條件。本文將詳細(xì)介紹c++ atomic原子編程中的Memory Order。2021-06-06
使用Visual Studio進(jìn)行動(dòng)態(tài)鏈接庫(kù)開發(fā)流程
這篇文章主要介紹了使用Visual Studio進(jìn)行動(dòng)態(tài)鏈接庫(kù)開發(fā)流程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-05-05
C++?二叉樹的實(shí)現(xiàn)超詳細(xì)解析
二叉樹可以簡(jiǎn)單理解為對(duì)于一個(gè)節(jié)點(diǎn)來(lái)說(shuō),最多擁有一個(gè)上級(jí)節(jié)點(diǎn),同時(shí)最多具備左右兩個(gè)下級(jí)節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)。本文將詳細(xì)介紹一下C++中二叉樹的實(shí)現(xiàn)和遍歷,需要的可以參考一下2022-03-03
Matlab利用prim算法實(shí)現(xiàn)迷宮的生成
普里姆算法(Prim算法),圖論中的一種算法,可在加權(quán)連通圖里搜索最小生成樹。本文將利用prim算法迷宮生成及其藝術(shù)渲染,感興趣的可以了解一下2022-10-10
C標(biāo)準(zhǔn)庫(kù)<assert.h>的實(shí)現(xiàn)詳解
這篇文章主要介紹了C標(biāo)準(zhǔn)庫(kù)<assert.h>的實(shí)現(xiàn),主要包括了<assert.h>的基本概念、實(shí)現(xiàn)及用法等,需要的朋友可以參考下2014-09-09
C程序?qū)崿F(xiàn)整數(shù)的素?cái)?shù)和分解問(wèn)題
這篇文章主要介紹了C程序?qū)崿F(xiàn)整數(shù)的素?cái)?shù)和分解問(wèn)題,對(duì)于算法的學(xué)習(xí)有不錯(cuò)的借鑒價(jià)值,需要的朋友可以參考下2014-09-09

