C++——将成员函数作为参数
在C++中,成员函数指针作为参数传递给其他函数和普通函数指针的传递是不同的,首先
我们来回顾一下普通函数指针的传递方法:
//--------------------------------------------------------------------------
int fun1(int i){
return i;
}
void fun2(int j, int (*p)(int)){
cout << p(j);
}
void main()
{
int i=1;
fun2(i,fun1);
}
//--------------------------------------------------------------------------
只要在参数声明中声明是相同参数个数、类型和相同返回类型的函数指针int (*p)(int
),传递时只需传函数名就可以了可是为什么在C++中,传递成员函数指针用此方法却不
能工作呢?我们先来回顾一下指针的概念,指针是指向一些内存地址的变量,既可以是
数据的地址也可以是函数的地址。C++的成员指针遵从同样的原则。困难的是所有的指针
需要一个地址,但在类内部没有地址;选择一个类的成员意味着在类中偏移。只有把这
个偏移和具体对象的开始地址结合,才能得到实际地址。成员指针的语法要求选择一个
对象的同时逆向引用成员指针。先来看看一个错误的例子:
//--------------------------------------------------------------------------
class A
{
public:
int fun1(int i){return i;};
};
void fun2(int j, int (A::*p)(int)){
cout <<p(j);
}
void main()
{
A oba;
int i=1;
fun2(i,oba.fun1); //this is an error
}
//--------------------------------------------------------------------------
当然,你可以把成员函数声明为static(静态函数),这样传递它的指针就像传递普通
函数一样,然而把成员函数定义成static类型无法真正解决问题,因为这样的话,该成
员函数就不能存取类中的非静态成员变量,而很多情况下既要求传递成员函数指针,又
要求该成员函数能够存取类中的非静态成员变量。
为了能够正确地传递成员函数指针,我们先来看看成员参数、成员函数指针正确的声明
方法:
//--------------------------------------------------------------------------
class A
{
public:
int i1;
int fun1(int i){
return i;
};
};
void main()
{
int (A::*fp1)(int); //声明fp1为class A中的成员函数指针
int A::*ip1; //声明ip1为class A中的成员变量指针
fp1=&A::fun1; //初始化fp1
ip1=&A::i1; //初始化ip1
ip1=&A::i1; //初始化ip1
A oba;
oba.*ip1=2;
(oba.*fp1)(oba.*ip1);
}
//--------------------------------------------------------------------------
接下来就可以构造含有成员函数指针参数的函数了:
void fun2(int j, A ob, int (A::*p)(int)){
cout <<(ob.*p)(j);
}
注意声明时必须加上一个对象参数A ob,因为只有把这个偏移和具体对象的开始地址结
合,才能得到实际地址。
另外,为了保证函数的健壮性和经济性,我们可以把对象参数改为对象指针参数:
void fun2(int j, A *obp, int (A::*p)(int)){
cout <<(obp->*p)(j);
}
为了通用,我们还可以把这个函数声明为通用函数:
template <class T>
void fun2(int j, T *obp, int (A::*p)(int)){
cout <<(obp->*p)(j);
}
这样就可以传递不同的类的成员函数指针给它了,以下为正确传递成员函数指针的例程:
//--------------------------------------------------------------------------
class A
{
public:
int fun1(int i){
return i;
};
};
template <class T>
void fun2(int j, T *obp, int (T::*p)(int)){
cout <<(obp->*p)(j);
}
void main()
{
int (A::*fp1)(int);
fp1=&A::fun1;
A oba;
A *obap=&oba;
int i=1;
fun2(i,obap,fp1);
}
//--------------------------------------------------------------------------
但是这样声明之后就不能再传递普通函数指针给函数fun2了,为了更加通用,当然可以
显式地重载一下这个函数,以便它也能使用普通函数指针参数:
//--------------------------------------------------------------------------
class A
{
public:
int fun1(int i){
return i;
};
};
template <class T>
void fun2(int j, T *obp, int (T::*p)(int)){
cout <<(obp->*p)(j);
}
void fun2(int j, int (*p)(int)){
cout << p(j);
}
int fun3(int i){
return i;
}
void main()
{
int (A::*fp1)(int);
fp1=&A::fun1;
A oba;
A *obap=&oba;
int i=1;
fun2(i,obap,fp1);
fun2(i,fun3);
}
//--------------------------------------------------------------------------
C++——将成员函数作为参数的更多相关文章
- c++中成员函数的参数名与成员变量名重合的问题
有一天写类的时候突然想到了这个问题,下面就来介绍如何解决这个问题. 定义一个类: class test{ public: void setnum(); void getnum(); private: ...
- linux 之 pthread_create 实现类的成员函数做参数
在C++的类中,普通成员函数不能作为pthread_create的线程函数,如果要作为pthread_create中的线程函数,必须是static ! 在C语言中,我们使用pthread_create ...
- C++ 类成员函数作为参数
#include <iostream> using namespace std; typedef int int32_t; struct IMsgBody{ int body; }; st ...
- Javascript基础--成员函数(六)
成员函数:也叫方法 1.常用方法 比如:我们希望对象不但有属性,还希望他有行为.(行为在程序中要靠函数来体现)(1) 添加speak函数,输出我是一个好人 (2) 添加jisuan函数,可以计算从1+ ...
- C++:类的成员函数定义方式
1.成员函数的第一种定义方式:在类声明中只给出成员函数的原型,而将成员函数的定义 放在类的外部. 返回值类型 类名::成员函数名(参数表) { 函数体 } class Point{ pub ...
- 类 this指针 const成员函数
C++ Primer 第07章 类 7.1.2 Sales_data类的定义如下: #ifndef SALES_DATA_H #define SALES_DATA_H #include <st ...
- C++中的const成员函数(函数声明后加const,或称常量成员函数)用法详解
http://blog.csdn.net/gmstart/article/details/7046140 在C++的类定义里面,可以看到类似下面的定义: 01 class List { 02 priv ...
- 介绍了如何取成员函数的地址以及调用该地址:C++
摘要:介绍了如何取成员函数的地址以及调用该地址. 关键字:C++成员函数 this指针 调用约定 一.成员函数指针的用法 在C++中,成员函数的指针是个比较特殊的东西.对普通的函数指针来说,可以视为一 ...
- const当做标记的函数重载,但是仅仅是限于类里面的成员函数
(1)我们知道函数的重载时根据函数的参数类型以及函数参数个数来重载的,不能用函数返回值来重载函数.但是有时候函数参数个数和函数参数类型重载函数会和默认参数发生冲突: int fun(int i,cha ...
随机推荐
- 关于iframe嵌套、动态获取iframe内的url、父页面重定向
1 $(function () { 2 //选择器是选择了easyui中的点击链接,出现新的iframe 3 $("a[target='mainFrame']").click(fu ...
- 【转】介绍设置Session失效的几种方法
转载地址:http://developer.51cto.com/art/201106/269493.htm Session对象是HttpSessionState的一个实例.该类为当前用户会话提供信息, ...
- 3G中的A-GPS移动定位技术
位置业务(LBS,Location Based Service)是指移动网络通过特定的定位技术来获取移动终端的位置信息,从而为终端用户提供附加服务的一种增值业务,可广泛应用于紧急救援.导航追踪.运输调 ...
- 算法心得2:关于k个最小和问题的思考
问题描述如下: 有k个整数数组,各包含k个元素.在每个数组中取一个元素加起来,可以得到k^k个和.求这些和中最小的k个值(重复计算的算多次). 如果同时考虑这k个数组的取值情况,其复杂程度不言而喻,并 ...
- Moo University - Financial Aid
Moo University - Financial Aid Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 6020 Accep ...
- 【20160924】GOCVHelper 图像增强部分(1)
图像增强是图像处理的第一步.这里集成了一些实际使用过程中有用的函数. //读取灰度或彩色图片到灰度 Mat imread2gray(string path){ Mat sr ...
- Rigidbody SweepTest测试
和Physics的投射差不多,SweepTest可以直接投射当前碰撞 但是比较遗憾的是它对MeshCollider的支持不是很好,需要勾选Convex 投射和Physics一样,只要加了碰撞器,不管勾 ...
- Android开发之Theme、Style探索及源码浅析
1 背景 前段时间群里有伙伴问到了关于Android开发中Theme与Style的问题,当然,这类东西在网上随便一搜一大把模板,所以关于怎么用的问题我想这里也就不做太多的说明了,我们这里把重点放在理解 ...
- UIEdgeInsetsMake, CGRectOffset等API参数详解
1, UIEdgeInsetsMake ( CGFloat top, CGFloat left, CGFloat bottom, CGFloat right ) 2,position点是相对suerL ...
- SELECT INTO FROM mysql Undeclared variable
使用SELECT INTO FROM进行数据表和数据的复制时,会提示Error Code: 1327. Undeclared variable: 这是因为mysql 数据库不支持 SELECT INT ...