【轉】C++指向類成員的指針的使用(詳細介紹)

【轉】C++指向類成員的指針的使用(詳細介紹)

默認分類 2009-09-06 20:39:57 閱讀176 評論0   字號: 訂閱

1.首先普通函數指針不能被賦值爲成員函數的地址,即使返回類型和參數完全匹配。例如:下面是的pfi是一個普通函數指針,它沒有參數,返回類型爲int:
 int (*pfi)();
若有兩個全局函數,HeightIs()和WidthIs():
 int HeightIs();
 int WidthIs();
則下面的的賦值操作是合法的:
 pfi = HeightIs();
 pfi = WidthIs();

但如今有一個類Screen也定義了兩個訪問函數-height()和width(),它們也沒有參數,
返回類型也爲int:
 inline int Screen::height() { return _height; }
 inline int Screan::width()  { return _width;  }
但是下面的賦值是非法的,會導致編譯錯誤產生。
 pfi = &Screen::height();

爲什麼會出現違例?因爲,成員函數有一個非成員函數不具有的屬性-它的類(class)。
指向成員函數的指針必須於其賦值的函數類型匹配,不是兩個方面而是三個方面:
(1)參數類型和個數(2)返回類型 (3) 它所屬的類類型。

成員函數指針和普通函數指針之間的不匹配是由於這兩種指針在表示上的區別。函數指針
存儲函數的地址,可以被用來直接調用那個函數。成員函數指針首
先必須被綁定在一個對象或者一個指針上,才能得到被調用對象的this 指針,然後才調
用指針所指的成員函數。在下面將看到成員函數指針怎樣被綁定到一個對象或指針上,
以便調用一個成員函數。

2.成員函數指針的聲明:
 拿下面這個類來說明:
 class Screen {
public:
 // 成員函數
 void home() { _cursor = 0; }
 void move( int, int );
 char get() { return _screen[_cursor]; }
 char get( int, int );
 bool checkRange( int, int );
 int height() { return _height; }
 int width() { return _width; }
 //....
public://修正
 string _screen;
 string::size_type _cursor;
 short _height;
 short _width;
};

成員函數指針的聲明要求擴展的語法,它要考慮類的類型。對指向類數據成員的指針也
是這樣。考慮Screen 類的成員_height 的類型。它的完整類型是”short 型的Screen 類的成
員“指向_height 的指針的完整類型是”指向short 型的Screen 類的成員的指針“這可以
寫爲:
 short Screen:*
指向short型的Screen類的成員的指針定義如下:
 short Screen::* ps_Screen;
ps_Screen 可以用_height 的地址初始化如下
 short Screen::*ps_Screen = &Screen::_height;

在數據成員指針和普通指針之間的不匹配也是由於這兩種指針的表示上的區別。普通指
針含有引用一個對象所需的全部信息。數據成員指針在被用來訪問數據成員之前,必須先被
綁定到一個對象或指針上。

定義一個成員函數指針需要指定函數返回類型,參數表和類。例如指向Screen 成員函
數並且能夠引用成員函數height()和width()的指針類型如下:
 int (Screen::*) ();
這種類型指定了一個指向類Screen的成員函數的指針,它沒有參數,返回值類型爲int。
指向成員函數的指針可被聲明,初始化及賦值如下
// 所有指向類成員的指針都可以用0 賦值
 int (Screen::*pmf1)() = 0;
 int (Screen::*pmf2)() = &Screen::height;
 pmf1 = pmf2;
 pmf2 = &Screen::width;
也可以用typedef 定義,這樣語法更容易讀。如:
 typedef Screen& (Screen::*Action)();
 Action default = &Screen::home;
 Action next = &Screen::forward;

3.怎樣使用指向類成員的指針
   類成員的指針必須總是通過特定的對象或指向改類型的對象的指針來訪問。是通過
使用兩個指向成員操作符的指針(針對類對象和引用的.* ,以及針對指向類對象的指針的->*)
(操作符.*和->*的說明如下:
pm-expression :
cast-expression
pm-expression .* cast-expression
pm-expression ->* cast-expression

The binary operator .* combines its first operand, which must be an object of class type,
with its second operand, which must be a pointer-to-member type.

The binary operator ->* combines its first operand, which must be a pointer to an object
of class type, with its second operand, which must be a pointer-to-member type.

In an expression containing the .* operator, the first operand must be of the class type
of the pointer to member specified in the second operand or of a type unambiguously derived
from that class.

In an expression containing the ->* operator, the first operand must be of the type "pointer
to the class type" of the type specified in the second operand, or it must be of a type
unambiguously derived from that class.

)

如下面例子:
 int (Screen::*pmfi)() = &Screen::height;
 Screen& (Screen::*pmfS)( const Screen& ) = &Screen::copy;
 Screen myScreen, *bufScreen;
 // 直接調用成員函數
 if ( myScreen.height() == bufScreen->height() )
 bufScreen->copy( myScreen );
 // 通過成員指針的等價調用
 if ( (myScreen.*pmfi)() == (bufScreen->*pmfi)() )
 (bufScreen->*pmfS)( myScreen );

類似地指向數據成員的指針可以按下列方式被訪問:
 typedef short Screen::*ps_Screen;
 Screen myScreen, *tmpScreen = new Screen( 10, 10 );
 ps_Screen pH = &Screen::_height;
 ps_Screen pW = &Screen::_width;
 tmpScreen->*pH = myScreen.*pH;
 tmpScreen->*pW = myScreen.*pW;

4.靜態類成員的指針:
    在非靜態類成員的指針和靜態類成員的指引之間有一個區別。指向類成員的指針語法不
能被用來引用類的靜態成員靜態類成員。是屬於該類的全局對象和函數它們的指針是普通
指針。

如:
class A{
public :
 static void f();
public:
 static int m_data;
};

指向m_data指針的定義如下:
 int *p = &A::m_data;

 //錯誤
 int A::* p = &A::m_data;
指向f函數指針可以這樣定義:它是一個普通的函數指針
 void (*ptrf)() = &A::f;

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/dremi/archive/2007/11/16/1888635.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章