`

《认清C++语言》---类成员的指针

 
阅读更多

有时,我们希望获得类的特定成员的指针,然后从一个对象或别的对象获得该成员,这时可以通过使用称为成员指针的特殊种类的指针。

成员指针包含类的类型以及成员的类型,成员指针只应用于类的非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 c2 = (asceScreen.*pmf) (); //等同与调用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 Action Menu[]; //类成员函数指针表

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()函数

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics