指向類成員的指針
在C++語言中,可以定義一個指針,使其指向類成員或成員函數,然後通過指針來訪問類的成員。這包括指向屬性成員的指針和指向成員函數的指針。
à 指向數據成員的指針
在C++語言中,可以定義一個指針,使其指向類成員。當屬性成員爲靜態和非靜態時,指針的使用也有不同。其中,指向非靜態數據成員的指針定義格式如下:
1. <數據類型> <類名>::*<指針名> [ = &<類名>::<非靜態數據成員>]
指向非靜態數據成員的指針在定義時必須和類相關聯,在使用時必須和具體的對象關聯。
2. <類對象名>.*<指向非靜態數據成員的指針>
指向靜態數據成員的指針的定義和使用與普通指針相同,在定義時無須和類相關聯,在使用時也無須和具體的對象相關聯。
假設已經定義了一個類student,該類有非靜態成員math,靜態成員chinese,代碼演示了指向它們的指針定義方式。
1. student s1;
2. int student::*pm=&student::math; //指向非靜態屬性
3. s1.*pm=100; //設置非靜態屬性
4. int *pc=&student::chinese; //指向靜態屬性
5. *pc=10; //設置靜態屬性
分析:該示例定義了指針pc和pm,分別指向類的靜態數據成員chinese和非靜態數據成員math。訪問pm時,必須使用類實例來修飾。而訪問pc時,與普通指針沒有區別。
à 指向成員函數的指針
定義一個指向非靜態成員函數的指針必須在三個方面與其指向的成員函數保持一致:參數列表要相同、返回類型要相同、所屬的類型要相同。定義格式如下:
1. <數據類型>(<類名>::*<指針名>)(<參數列表>)[=&<類名>::<非靜態成員函數>]
使用指向非靜態成員函數的指針的方法和使用指向非靜態數據成員的指針的方法相同,格式如下:
2. (<類對象名>.*<指向非靜態成員函數的指針>)(<參數列表>);
指向靜態成員函數的指針和普通指針相同,在定義時無須和類相關聯,在使用時也無須和具體的對象相關聯。
3. <數據類型>(*<指針名>)(<參數列表>)[=&<類名>::<靜態成員函數>]
假設類student有非靜態成員函數f1,非靜態成員函數f2,代碼演示指向它們的函數指針的定義方式。
1. student s1;
2. float (student::*pf1)()=&student::f1; //指向非靜態成員函數的指針
3. (s1.*pf1)(); //調用指向非靜態成員函數的指針
4. void (*pf2)()=&student::f2; //指向靜態成員函數的指針
5. pf2(); //調用靜態成員函數
分析:指向非靜態成員函數時,必須用類名作限定符,使用時則必須用類的實例作限定符。指向靜態成員函數時,則不需要使用類名作限定符。
分析:
pointName = &ClassName::member;
即將類中指定成員的地址賦給指針變量,其中ClassName是已定義的類名,而member是數據成員名。顯然,編譯系統對類名並不分配存儲空間,也就沒有一個絕對地址。所以這種賦值,是取該成員相對於該類的所在對象中的偏移量,即相對地址(距離開始位置的字節數)。對類中的任一成員,其偏移量是一個常數。因這種指針變量的值是一個相對地址,不是指向某一個對象中的數據成員的絕對地址,所以不能單獨使用這種指針變量來訪問數據成員。如*pointName 是不允許的。由於這種指針變量並不是類的成員,所以使用它只能訪問對象的公有數據成員。若要訪問對象的私有數據成員,必須通過成員函數來實現。
實例如下:#include <iostream>
using namespace std;
class Point3d
{
public:
Point3d(){x = y = z = -1;}
float sum(){return x+y+z;}
public:
float x,y,z;
static float s;
};
float Point3d::s = 100;
int main () {
cout<<Point3d::s<<endl;
Point3d p3d;
float Point3d::*pfm = &Point3d::x;
cout<<p3d.*pfm<<endl;
float *pfsm = &Point3d::s;
cout<<*pfsm<<endl;
float (Point3d::*pff)() = &Point3d::sum;
cout<<(p3d.*pff)()<<endl;
}