类的成员函数指针作为参数传递给其他函数和普通函数指针的传递是不同的
2016-07-10 22:45
393 查看
类的成员函数指针作为参数传递给其他函数和普通函数指针的传递是不同的,普通函数指针的传递
只要在参数声明中声明是相同参数个数、类型和相同返回类型的函数指针int (*p)(int),传递时只需传函数名就可以了.
可是传递成员函数指针用此方法却不能工作。指针是指向一些内存地址的变量,既可以是数据的地址也可以是函数的地址。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
}
//---------------------------------------------------------------------------
为了能够正确地传递成员函数指针,我们先来看看成员参数、成员函数指针正确的声明方法:
//---------------------------------------------------------------------------
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
A oba;
oba.*ip1=2;
(oba.*fp1)(oba.*ip1);
}
//---------------------------------------------------------------------------
以下为正确传递成员函数指针的例子:
//---------------------------------------------------------------------------
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为class A中的成员函数指针
fp1=&A::fun1; //初始化fp1
A oba;
A *obap=&oba;
int i=1;
fun2(i,obap,fp1);
}
//---------------------------------------------------------------------------
当然,可以把成员函数声明为static(静态函数),这样传递它的指针就像传递普通函数一样。但是又涉及一个问题:类中如何在static 函数中调用 非static 函数 。
方法:使用静态成员函数
使回调成员函数为静态。因为静态成员函数不带隐含式参数“this”。因此,可以将其参数中的地址当作是普通函数的指针来使用。如果要从静态成员函数中访问对象的数据成员,显式传入对象的地址即可。例如:
//---------------------------------------------------------------------------
class Hack
{
private:
int x;
public:
int get_x();// 非静态成员函数
static void func(Hack * pthis); // 静态成员函数
void func2(); // 非静态成员函数
};
void Hack::func(Hack * pthis)
{
int y = pthis->get_x(); // 访问对象的数据成员
}
//---------------------------------------------------------------------------
只要在参数声明中声明是相同参数个数、类型和相同返回类型的函数指针int (*p)(int),传递时只需传函数名就可以了.
可是传递成员函数指针用此方法却不能工作。指针是指向一些内存地址的变量,既可以是数据的地址也可以是函数的地址。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
}
//---------------------------------------------------------------------------
为了能够正确地传递成员函数指针,我们先来看看成员参数、成员函数指针正确的声明方法:
//---------------------------------------------------------------------------
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
A oba;
oba.*ip1=2;
(oba.*fp1)(oba.*ip1);
}
//---------------------------------------------------------------------------
以下为正确传递成员函数指针的例子:
//---------------------------------------------------------------------------
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为class A中的成员函数指针
fp1=&A::fun1; //初始化fp1
A oba;
A *obap=&oba;
int i=1;
fun2(i,obap,fp1);
}
//---------------------------------------------------------------------------
当然,可以把成员函数声明为static(静态函数),这样传递它的指针就像传递普通函数一样。但是又涉及一个问题:类中如何在static 函数中调用 非static 函数 。
方法:使用静态成员函数
使回调成员函数为静态。因为静态成员函数不带隐含式参数“this”。因此,可以将其参数中的地址当作是普通函数的指针来使用。如果要从静态成员函数中访问对象的数据成员,显式传入对象的地址即可。例如:
//---------------------------------------------------------------------------
class Hack
{
private:
int x;
public:
int get_x();// 非静态成员函数
static void func(Hack * pthis); // 静态成员函数
void func2(); // 非静态成员函数
};
void Hack::func(Hack * pthis)
{
int y = pthis->get_x(); // 访问对象的数据成员
}
//---------------------------------------------------------------------------
相关文章推荐
- BZOJ 1798: [Ahoi2009]Seq 维护序列seq
- swift 高仿爱鲜蜂
- HTTP返回码总结
- java中的拷贝(一)
- 杂记一
- 巩固基础篇:数独彩色版(计算时间) 经典回溯法(可与八皇后问题对比)
- hiho #1051 : 补提交卡
- C++中括号()操作符的重载举例及解析
- lib and dll
- JAVA学习笔记three:异常
- 没有与这些操作数匹配的运算符
- 产生任意数
- whose view is not in the window hierarchy
- 基于Android实现保存图片到本地并可以在相册中显示出来
- 欢迎使用CSDN-markdown编辑器
- java 集合之ArrayList集合元素重复删除
- HttpClient--BasicNameValuePair
- 谈Android模拟点击的价值和实现
- Java 多线程同步机制
- Robot FrameWork学习网址