有时,我们希望获得类的特定成员的指针,然后从一个对象或别的对象获得该成员,这时可以通过使用称为成员指针的特殊种类的指针。
成员指针包含类的类型以及成员的类型,成员指针只应用于类的非static成员。因为static类成员不是任何对象的组成部分,因此不需要特殊语法来指向static成员,static成员指针是普通指针。
先看下面的类:
class ASCEScreen
{
public:
typedef std::string::size_type index;
wchar_t get() const;
wchar_t get(index ht, index wd) const;
private:
std::string contents;
index cursor;
index height, width;
};

1)定义数据成员的指针
可以指向contents的指针的完全类型是:“指向std::string类型的ASCEScreen类成员的指针”,而可以指向ASCEScreen类的std::string成员的指针定义就是:
std::string ASCEScreen::*ps_ASCEScreen;
可以用contents的地址初始化ps_ASCEScreen:
std::string ASCEScreen::*ps_ASCEScreen = &ASCEScreen::contents;

2)定义成员函数的指针
成员函数的指针必须在三个方面与它所指函数的类型相匹配:
1---函数形参的类型和数目,包括成员是否为const;
2---返回类型;
3---所属类的类型。
通过指定函数返回类型、形参表和类来定义成员函数的指针,例如可引用不接受形参的get版本的ASCEScreen成员函数的指针具有如下类型:
wchar_t (ASCEScreen::*pmf) () const = &ASCEScreen::get;
带两个形参的get函数版本的指针定义如下:
wchar_t (ASCEScreen::*pmf) (ASCEScreen::index, ASCEScreen::index) const;
pmf = &ASCEScreen::get;

3)为成员指针使用类型别名
类型别名可以使成员指针更容易阅读,下面的类型别名将Action定义成带两个形参的get函数版本的类型的另一个名字:
typedef wchar_t (ASCEScreen::*Action) (ASCEScreen::index, ASCEScreen::index) const;
Action现在就是类型“ASCEScreen类的接受两个index类型形参并返回wchar_t的成员函数的指针”的名字了。使用类型别名,可以将get指针定义简化为:
Action ASCEGet = &ASCEScreen::get;
可以使用成员指针函数类型来声明函数形参和函数返回类型:
ASCEScreen& action(ASCEScreen&, Action = &ASCEScreen::get);
这个函数声明为接受两个形参:ASCEScreen对象的引用,以及ASCEScreen类接受两个index类型形参并返回wchar_t的成员函数的指针。
这样就可以通过传递ASCEScreen类中适当成员函数的指针或地址调用action函数:
ASCEScreen asceScreen;
//等价的调用
action(asceScreen);
action(asceScreen, get);
action(asceScreen, &ASCEScreen::get); //显式传地址

类似于成员访问操作符.和->,.*和->*是两个新的操作符:
成员指针解引用操作符.*从对象或引用获取成员;
成员指针箭头操作符->*通过对象的指针获取成员。

4)使用成员函数的指针
可以这样调用不带形参的get函数版本:
wchar_t (ASCEScreen::*pmf) () const = &ASCEScreen::get;
ASCEScreen asceScreen;
wchar_t c1 = asceScreen.get();
wchar_t //等同与调用get()

ASCEScreen *pasceScreen = &asceScreen;
c1 = pasceScreen->get();
c2 = (pasceScreen->*pmf) (); //等同于调用get()

5)使用数据成员的指针
相同的成员指针操作符用于访问数据成员:
ASCEScreen::index ASCEScreen::*pindex = &ASCEScreen::width;
ASCEScreen asceScreen;
ASCEScreen::index ind1 = asceScreen.width;
ASCEScreen::index ind2 = asceScreen.*pindex; //同上

ASCEScreen *pasceScreen = &asceScreen;
ind1 = pasceScreen->width;
ind2 = pasceScreen->*pindex; //同上

6)成员指针函数表
函数指针和成员函数指针的一个公共用途是将它们存放在函数表中。函数表是函数指针的集合,在运行时从中选择给定的调用。
对具有几个相同类型成员的类来说,可以使用这样的表来从这些成艳的集合中选一个运行:
class ASCEScreen
{
public:
...
ASCEScreen& home();
ASCEScreen& forward();
ASCEScreen& back();
ASCEScreen& up();
ASCEScreen& down();
public:
typedef ASCEScreen& (ASCEScreen::*Action) ();
static //类成员函数指针表

enum Directions {HOME, FORWARD, BACK, UP, DOWN};
ASCEScreen& move(Directions);
};

//move函数接受枚举成员并调用相应的函数
ASCEScreen& ASCEScreen::move(Directions cm)
{
(this->*Menu[cm]) (); //调用函数
return *this;
}

//定义和初始化成员函数指针表Menu[]
ASCEScreen::Action ASCEScreen::Menu[] = {&ASCEScreen::home, &ASCEScreen::forward,
&ASCEScreen::back, &ASCEScreen::up, &ASCEScreen::down};
使用如下:
ASCEScreen asceScreen;
asceScreen.move(ASCEScreen::HOME); //调用asceScreen.home()函数
asceScreen.move(ASCEScreen::DOWN);//调用asceScreen.down()函数