C++指向类成员的指针的使用(详细介绍)

来源:互联网 发布:淘宝运营表格 编辑:程序博客网 时间:2024/05/22 04:47

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; 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 入盆了又出来了怎么办 大腿前突小腿后怎么办 英语不好高二了怎么办 断奶后又复吸怎么办 招联金融综合评定不足怎么办 git本地分支比远程高怎么办 娃儿上嘴唇里面破了怎么办 错过了各大招聘怎么办 优秀团员申请表没有获奖情况怎么办 大学生毕业学生登记表涂改了怎么办 c语言挂科了怎么办 吸入腐蚀性气体鼻子流血了怎么办 腰劳损痛的厉害怎么办 两个宝宝斜颈左边力量差怎么办 姿势不正确引起的习惯性斜颈怎么办 一岁宝宝有点斜颈怎么办 六个月宝宝有点斜颈怎么办 5月宝宝有点斜颈怎么办 半岁宝宝头偏怎么办 肌性斜颈成年后怎么办 5个月孩子脖子歪怎么办 宝宝一岁多头歪怎么办 四个月宝宝歪脖子怎么办 1岁宝宝脖子歪怎么办 宝宝脖子是歪的怎么办 小孩脖子睡歪了怎么办 脸部三角区肿了怎么办 面部三角区挤了怎么办 胳膊扭着了肿了怎么办 多囊卵巢综合症治不好怎么办 胳膊受了风发麻怎么办 胳膊抻筋了很疼怎么办 腰抻了怎么办最有效 孩子胳膊抻着了怎么办 胳膊伤筋了疼怎么办 宝宝胳膊抻了疼怎么办 练完普拉提头晕怎么办 生完孩子腰背疼怎么办 宝宝不肯把屎尿怎么办 存的电话删除了怎么办 脚踝的韧带断了怎么办