指向类成员的指针(Pointers to Class Members)

原文 http://old.blog.edu.cn/user2/wanglina/archives/2006/1241853.shtml 

 

  • 类成员的类型

指向成员函数的指针必须与向其赋值的函数类型匹配,不是两个而是三个方面都要匹配:1 .参数的类型和个数   2 .返回类型 3 .它所属的类类型

普通函数指针和成员函数指针:

函数指针存储函数的地址,可以被用来直接调用那个函数。成员函数指针首先必须被绑定在一个对象或者一个指针上,才能得到被调用对象的this 指针,然后才调用指针所指的成员函数。

指向类数据成员的指针:

考虑Screen 类的成员height 的类型,它的完整类型是:short 型的Screen 类的成员。指向_height 的指针的完整类型是“指向short 型的Screen 类的成员的指针”,这可以写为
short Screen::*

普通指针含有引用一个对象所需的全部信息,数据成员指针在被用来访问数据成员之前,必须先被绑定到一个对象或指针上。

定义一个成员函数指针需要指定函数返回类型,参数表和类。例如:

指向Screen 成员函数,并且能够引用成员函数height()和width()的指针类型如下:
int (Screen::*) ()
这种类型指定了一个指向类Screen 的成员函数的指针,它没有参数,返回值类型为int。指向成员函数的指针可被声明初始化及赋值如下:
// 所有指向类成员的指针都可以用0 赋值
int (Screen::*pmf1)() = 0;
int (Screen::*pmf2)() = &Screen::height;
pmf1 = pmf2;
pmf2 = &Screen::width;
使用typedef 可以使成员指针的语法更易读,例如下面的类型定义:
Screen& ( Screen::* ) ()

也就是指向Screen 类成员函数的一个指针该函数,没有参数,返回Screen 类对象的引用,它可以被下列typedef 定义Action 所取代:
typedef Screen& (Screen::*Action)();
Action default = &Screen::home;
Action next = &Screen::forward;

  • 使用指向类成员的指针

类成员的指针必须总是通过特定的对象或指向该类类型的对象的指针来访问。我们通过使用两个指向成员操作符的指针(针对类对象和引用的.* 以及针对指向类对象的指针的->*)来做到这一点。例如,如下所示,我们通过成员函数的指针调用成员函数:
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;

  • 静态类成员的指针

静态类成员是属于该类的全局对象和函数。它们的指针是普通指针。(请记住静态成员函数没有this 指针

指向静态类成员的指针的声明看起来与非类成员的指针相同。解引用该指针不需要类对象。例如,我们再来看一下类Account:
class Account {
public:
static void raiseInterest( double incr );
static double interest() { return _interestRate; }
double amount() { return _amount; }
private:
static double _interestRate;
double _amount;
string _owner;
};
inline void Account::raiseInterest( double incr )
{
_interestRate += incr;
}

指向_interestRate 的指针定义如下
// OK: 是 double*, 而不是 double Account::*
double *pd = &Account::_interestRate;
它被解引用的方式与普通指针一样,不需要相关的类对象,例如:
Account unit;
// 用普通的解引用操作符
double daily = *pd /365 * unit._amount;

指向interest()的指针的类型是一个普通函数指针:
// 正确
double (*) ()
而不是类Account 的成员函数的指针
// 不正确
double (Account::*) ()
这个指针的定义和对interest()的间接调用处理方式与非类的指针相同。
// ok: douple(*pf) () 不是 double(Account::*pf)()
double (*pf)() = &Account::interest;

 

更多详细请参考:

1. http://msdn.microsoft.com/en-us/library/t7ee06tw(VS.80).aspx 

2. http://msdn.microsoft.com/en-us/library/k8336763.aspx 

3. http://msdn.microsoft.com/en-us/library/f2wbycwh(VS.80).aspx 

4. http://blog.sina.com.cn/s/blog_4bc03a14010009ph.html 

5. http://blog.chinaunix.net/u/8681/showart_2030504.html 

6. http://book.51cto.com/art/200909/154177.htm 

7. http://blog.csdn.net/metasearch/archive/2008/05/13/2443343.aspx 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值