分享方式:


成員的指標

成員指標宣告是特殊的指標宣告。 會使用下列序列宣告指標:

storage-class-specifiersopt cv-qualifiersopt type-specifier ms-modifieropt qualified-name ::* cv-qualifiersopt identifier pm-initializeropt ;

  1. 宣告規範:

    • 選擇性的儲存類別規範。

    • 選用 constvolatile 指定名稱。

    • 類型指定名稱:類型的名稱。 其是指向之成員的類型,而不是類別的類型。

  2. 宣告子:

    • 選擇性的 Microsoft 專有修飾詞。 如需詳細資訊,請參閱 Microsoft 專有的修飾詞 (部分機器翻譯)。

    • 包含指向成員之類別的限定名稱。

    • :: 運算子。

    • * 運算子。

    • 選用 constvolatile 指定名稱。

    • 為成員指標命名的識別項。

  3. 選用成員指標初始設定式:

    • = 運算子。

    • & 運算子。

    • 類別的限定名稱。

    • :: 運算子。

    • 適當類型類別之非靜態成員的名稱。

一如往常,單一宣告允許使用多個宣告子 (和任何關聯的初始設定式)。 成員的指標不可指向類別的靜態成員、參考類型的成員或 void

類別的成員指標與一般指標不同,因為這類指標同時包含成員類型及該成員所屬類別的類型資訊。 一般指標只能識別記憶體中的單一物件 (能取得其位址)。 類別的成員指標可以在類別的任何執行個體中識別該成員。 下列範例宣告類別、Window 和某些成員資料指標。

// 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 是任何 Window 成員類別的指標,該成員類別的類型為 char*pwCaption 的類型是 char * Window::*。 下一個程式碼片段會宣告 SetCaptionGetCaption 成員函式的指標。

const char * (Window::* pfnwGC)() = &Window::GetCaption;
bool (Window::* pfnwSC)( const char * ) = &Window::SetCaption;

pfnwGCpfnwSC 指標分別指向 GetCaption 類別的 SetCaptionWindow。 程式碼會使用成員指標 pwCaption,將資訊直接複製到視窗標題:

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';

.*->* 運算子 (成員指標運算子) 之間的差異在於,.* 運算子會選取指定物件或物件參考的成員,而 ->* 運算子會透過指標選取成員。 如需有關這些運算子的詳細資訊,請參閱使用成員指標運算子的運算式

成員指標運算子的結果是成員類型。 在此案例中,此名稱為 char *

下一個程式碼片段會使用成員指標叫用 GetCaptionSetCaption 成員函式:

// 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 );

成員指標的限制

靜態成員的位址不是成員的指標。 而是某一個靜態成員實例的一般指標。 給定類別的所有物件只存在一個靜態成員實例。 這表示您可以使用一般傳址 (&) 和取值 (*) 運算子。

成員指標和虛擬函式

透過成員指標函式叫用虛擬函式的運作方式與直接呼叫函式一樣。 在 v 資料表中查閱正確的函式並叫用之。

就如以往一般,虛擬函式運作的關鍵在於透過基底類別的指標叫用 (如需虛擬函式的詳細資訊,請參閱虛擬函式。)

下列程式碼將示範如何透過成員指標函式叫用虛擬函式:

// 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" << endl;
}

class Derived : public Base
{
public:
    void Print();  // Print is still a virtual function.
};

void Derived::Print()
{
    cout << "Print function for class Derived" << endl;
}

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