当前位置:首页 > 民俗文化

成员函数 浅谈C++指针直接调用类成员函数

http://soft.chinabyte.com/database/187/12133187.shtml

如果有好文章,

在编程工作中,我们经常会遇到通过一个“类”中的函数指针来调用成员函数的需求。比如在一个类中使用C++标准库中的排序函数qsort,由于qsort参数需要一个“比较函数”指针,如果“类”使用一个成员函数作为“比较函数”,就需要将这个成员函数的指针传递给qsort进行调用。本文讨论的由指针调用的类的成员函数包括以下三种情况:

(1).将“类”的成员函数指针分配给相同类型的非成员函数指针,例如:

例1

(2)在一个“类”中,有标准库函数,比如qsort,或者其他全局函数,用函数指针调用类的成员函数。例如:

例2:

(3)在同一个“类”中,一个成员函数调用另一个成员函数,如:

例3:

以上三种情况的代码语法都没有明显错误。在一些早期的编译环境中,例如VC++ 4.0,通常可以编译它,或者最多给出一个警告。后来的编译工具,如VC++6.0等常用的C++编译软件,都无法用上述代码编译,并指出以下错误(以用VC++ 6.0编译的第三种情况为例):

错误c 2664:“MemberFun 1”:无法将参数1从“void (void)”转换为“void(_ cdecl *)(void)”

作用域中没有同名的函数与目标类型匹配

也就是说,在Memberfun1参数中调用的函数类型错误。

根据上面的提示,仅仅改变函数的类型是无法消除错误的。但是,如果简单地将这些函数从类的定义中去掉,就可以在不做任何更改的情况下消除错误。通过编译,以第三种情况为例,可以编译出以下代码:

第一种和第二种情况与第三种情况完全相同。

所以可以得出结论,以上三种情况编译失败的原因不是函数类型调用不正确,而是和“类”有关。在编译失败的情况下,用函数指针调用类的成员函数,而在编译的情况下,用函数指针调用非成员函数,函数的类型完全相同。那么,类的成员函数指针和非成员函数指针有什么区别呢?

在下面的程序中,sizeof()函数可以用来检查各种“类”的成员函数指针和非成员函数指针的长度(大小),并输出到屏幕上。

输出结果是(用VC++6.0编译,运行在Win98操作系统上,其他操作系统可能不一样):

一般非成员函数指针长度= 4

-类的成员函数指针长度-

Test3类成员函数指针长度=4

Test5类成员函数指针长度=8

Test4类成员函数指针长度=12

测试类成员函数指针长度=16

以上结果表明,在32位Win98操作系统中,一般函数指针的长度为4字节(32位),而类成员函数指针的长度随着类的定义、继承类型和类的关系而变化,从没有继承类的4字节(32位)(Test3)到有虚拟继承的12字节(96位)(Test4 (Test 4)只有未定义的类(Test)是声明的,因为与它相关的一些信息不清楚,最大成员函数指针为16字节(128位)。显然,与一般的函数指针不同,“类”的成员函数指针不仅包含成员函数地址的信息,还包含与类属性相关的信息。因此,一般函数指针和类成员函数指针是根本不同的类型。当然不可能用一般的函数指针直接调用类成员函数,这也是本文开头提到的三种情况出现编译错误的原因。虽然用早期版本的编译软件编译还是可以通过的,但是会给程序留下严重的隐患。

至于为什么是指向类成员函数的指针,它们的长度差别很大,从32位到128位不等。由于没有微软官方数据,只能猜测VC++6.0在编译时优化了指向类成员函数的指针,尽可能缩短指针长度。毕竟,使用128位或96位指针会对32位操作系统的程序性能产生影响。但是,无论如何优化,类成员函数指针包含一定量的Objects信息是肯定的。其他操作系统和编译软件是否进行过类似的处理,读者可以使用上述程序自行验证。

那么,在需要的时候,如何用指针调用类的成员函数呢?可以考虑以下方法:

(1)将要调用的成员函数设置为静态类型,例如,在前面的示例2中,在Test2类成员函数Compare的定义之前添加static,如下所示(更改以粗体显示):

已成功编译更改的代码。原因是静态类型的成员函数与类分离,其函数指针不包含对象信息,与一般函数指针一致。这种方法虽然简单,但有两个缺点:1。被调用的函数成员定义中不能出现任何类成员(包括变量和函数);2.由于使用静态成员,类在继承时受到限制。

(2)使用一个函数参数包含对象信息的静态类型的成员函数间接调用其他成员函数,以例3为例,对Test3类进行如下修改(修改为加粗类型),main()函数不变,可以顺利通过编译:

这种间接方法对成员函数没有限制,克服了第一种方法的成员函数不能使用任何类成员的缺点,但类的继承仍然受到静态成员的限制。

(3)使用一个全局函数作为中间间接调用类的成员函数,以例3为例,代码修改如下(编译并传递VC++6.0):

这个方法不需要任何成员函数,但是需要更多的代码。

除了上述三种方法之外,还有其他方法,比如在汇编级修改代码来解决上述问题,这些都超出了本文的范围。

结论:函数指针不能直接调用类的成员函数,应采用间接方法。原因是成员函数指针和一般的函数指针有着根本的区别。成员函数指针不仅包含地址信息,还携带其所属对象的信息。本文提供了三种间接调用成员函数的方法。这三种方法各有利弊,适合不同的场合。

希望通过以上内容的介绍,能给大家带来帮助。

觉得这篇文章有帮助?请与更多人分享

关注CPP开发者

查看更多精选的C/C++技术文章

↓↓↓

1.《成员函数 浅谈C++指针直接调用类成员函数》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《成员函数 浅谈C++指针直接调用类成员函数》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/guoji/1645870.html

上一篇

暗黑3官网 IGN9.0评Swtich版《暗黑3》却遭国服玩家嫌弃:绝对不买!

下一篇

世界上最大的盆地 世界上海拔最高的盆地是哪个盆地

朱孝天微博 F4成员朱孝天过生日,韩雯雯晒帅气侧颜照示爱老公

  • 朱孝天微博 F4成员朱孝天过生日,韩雯雯晒帅气侧颜照示爱老公
  • 朱孝天微博 F4成员朱孝天过生日,韩雯雯晒帅气侧颜照示爱老公
  • 朱孝天微博 F4成员朱孝天过生日,韩雯雯晒帅气侧颜照示爱老公
外媒:中国向联合国成员国发照会,敦促不要参加美英策划的涉疆挑衅活动! 究竟是怎么一回事?

外媒:中国向联合国成员国发照会,敦促不要参加美英策划的涉疆挑衅活动! 究竟是怎么一回事?

路透社根据7日看到的一份照会发布“独家报道”称,中国敦促联合国成员国不要参加美国、英国和德国计划于下周举行的涉疆问题活动。...

hac成员 hac俱乐部Mr.J到底是谁?HAC俱乐部入会标准是怎样的?

  • hac成员 hac俱乐部Mr.J到底是谁?HAC俱乐部入会标准是怎样的?
  • hac成员 hac俱乐部Mr.J到底是谁?HAC俱乐部入会标准是怎样的?
  • hac成员 hac俱乐部Mr.J到底是谁?HAC俱乐部入会标准是怎样的?

谭春玲 集团公司党组成员、总会计师王云林 一行到河南航天调研指导工作

  • 谭春玲 集团公司党组成员、总会计师王云林 一行到河南航天调研指导工作
  • 谭春玲 集团公司党组成员、总会计师王云林 一行到河南航天调研指导工作
  • 谭春玲 集团公司党组成员、总会计师王云林 一行到河南航天调研指导工作
chyna北京一夜 得到名宿认可!DX成员盛赞WWE中国女将李霞:她就是NXT的未来

chyna北京一夜 得到名宿认可!DX成员盛赞WWE中国女将李霞:她就是NXT的未来

DX和WWE名人堂肖恩·沃特曼最近更新了他的播客节目,在此期间,他评为2019年最佳NXT。以下是精华总结: 年度NXT活动: “NXT接手了卡迪夫的大赛。因为每场比赛都很精彩,主战都很突出。” 年度NXT竞赛: “泰勒贝特vs沃尔特。太经典太创新了。” 年度最具突破性的奖项: “基思·李。里...

4am 4am战队老板是谁?4am战队成员都有谁

  • 4am 4am战队老板是谁?4am战队成员都有谁
  • 4am 4am战队老板是谁?4am战队成员都有谁
  • 4am 4am战队老板是谁?4am战队成员都有谁

4am战队 4am战队老板是谁?4am战队成员都有谁

  • 4am战队 4am战队老板是谁?4am战队成员都有谁
  • 4am战队 4am战队老板是谁?4am战队成员都有谁
  • 4am战队 4am战队老板是谁?4am战队成员都有谁

4am战队成员 4am战队老板是谁?4am战队成员都有谁

  • 4am战队成员 4am战队老板是谁?4am战队成员都有谁
  • 4am战队成员 4am战队老板是谁?4am战队成员都有谁
  • 4am战队成员 4am战队老板是谁?4am战队成员都有谁