c++函数指针3.0

那么,既然这个函数是非静态成员函数,那么这个函数支不支持动态绑定呢?换句话说就是,我们声明的函数指针是基类的函数指针,子类覆写了这个函数,那么,用子类对象调用的时候,是调用基类的函数还是子类的函数呢?我们看一个例子:

// C++Test.cpp : 定义控制台应用程序的入口点。
//

//#include “stdafx.h”
//#include
//#include
//#include
using namespace std;

//Base类
class Base
{
public:
//虚函数
virtual void Print(int num)
{
cout << “base: ” << num << endl;
}
};

class Child : public Base
{
public:
//覆写基类的Print方法
void Print(int num) override
{
cout << “child: ” << num << endl;
}
};

//定义一个成员函数指针
typedef void (Base::*pFunc)(int);

int _tmain(int argc, _TCHAR* argv[])
{
Base base;
Child child;
//给函数指针赋值的时候,必须是用声明函数指针的类来赋值(此处为Base)
pFunc func = &(Base::Print);
//通过base对象调用函数指针
(base.*func)(1);
//通过child对象调用函数指针
(child.*func)(1);
//查看函数指针的大小
cou t << “sizeof Member Function: ” << s izeof(func) << endl;

system("pause");
return 0;

}
结果:
base: 1
child: 1
sizeof Member Function: 4
请按任意键继续…

从上面的结果,我们看出,在最后使用函数指针的时候,这个this指针的对象可以是我们声明函数指针的时候的对象的子类,并且如果我们覆写了基类的函数,是可以调用子类的函数的(注意是覆写基类的virtual函数,如果只是单纯的覆盖是没有多态效果的)。

我们分析一下原因,还是这样看待这个函数指针,把它看成普通函数指针增加了一个类对象的this指针作为参数,这个形参我们可以声明为基类的指针,我们给实参的时候,可以给基类的对象,当然也可以给子类对象,这就跟我们普通函数传递参数的情况一样,然后这个参数传递进去,如果有virtual函数,那么就可以触发多态。但是我们在给函数指针赋值的时候,却只能使用基类的函数,因为我们没有声明子类的函数。

四.函数指针的作用
1.函数指针作为函数的参数
有了函数指针,我们就可以像传递普通指针那样将一个函数作为参数传递给另一个函数,这大大的增加了我们编程的灵活性。比如处理一个事务,我们可以随意更换处理的handler,当然,使用面向对象思想,通过多态也可以实现相应的功能。我们看一个例子:
// C++Test.cpp : 定义控制台应用程序的入口点。
//

//#include “stdafx.h”
//#include
//#include
// #include
using namespace std;

//定义pcall这种函数指针的类型
typedef int (*pcall)(int, int);

//处理函数,接受一个pcall类型的函数作为参数
void Func(pcall p, int x, int y)
{
cout << “begin func: ” << endl;
cout <<”result is : “<< p(x, y) << endl;
cou t << “end func”<< endl;
}

//加法函数
int AddFunc(int x, int y)
{
return x + y;
}

//减法函数
int SubFunc(int x, int y)
{
return x - y;
}

int _tmain(int argc, _TCHAR* argv[])
{
//将函数指针作为参数传递给函数
//&符号可以省略
Func(&AddFunc, 2, 1);
Func(&SubFunc, 2, 1);

system("pause");
return 0;

}
结果:
begin func:
result is : 3
end func
begin func:
result is : 1
end func
请按任意键继续…

2.函数回调
能将函数作为参数进行传递并不是我们最终的目的,函数指针最有用的功能之一就是回调。关于函数普通调用和回调,我们用买东西做个比喻,普通调用就好比我们直接去买东西,到了商店就买到了东西;而函数回调就好比我们去蛋糕店预定一个蛋糕,这时蛋糕店肯定会留下你的联系方式,当蛋糕做好了,蛋糕店就会给你打电话,让你去取蛋糕。从这里,我们看到,函数回调也是需要有一些前提步骤的,首先我们要将回调的函数注册给调用方,这就好比我们去蛋糕店留下了联系方式,而当某种条件满足了的时候,就调用回调函数,这个条件在我们的例子中就是蛋糕做好了。最后,蛋糕店给你打电话让你去取蛋糕,这个过程就是调用我们注册好的函数了。
回调函数有什么好处呢?还是拿买蛋糕的例子来说,如果不用回调函数,那么,我们如果去蛋糕店买蛋糕,买完之后,我们并不知道蛋糕什么时候做好,那么要么我们就得一直呆在蛋糕店等着,要么我们就得隔一会儿给蛋糕店打一个电话,问一下蛋糕有没有做好。看一个没有用回调函数的例子:
// C++Test.cpp : 定义控制台应用程序的入口点。
//

//#include “stdafx.h”
//#include
//#include
//#include
using namespace std;

class Baker
{
private:
int m_iTime; //做蛋糕的时间
static const int m_iMaxTime = 10;//假设10分钟做完
public:
//做蛋糕,如果做好了返回true,否则返回false
bool MakeCake();
//构造函数
Baker();
};

Baker::Baker() : m_iTime(0){}

bool Baker::MakeCake()
{
//假设每次调用该函数,m_iTime+1
m_iTime += 1;
if (m_iTime == m_iMaxTime)
{
cout << “蛋糕做好了!” << endl;
return true;
}
return false;
}

//客户函数
void GetMyCake()
{
cout << “我来取蛋糕啦!” << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
//创建一个蛋糕店
Baker baker;
//做蛋糕
while(1)
{
//客户如果想第一时间知道蛋糕做没做好,就必须每时每刻查看蛋糕的情况
if (baker.MakeCake())
{
GetMyCake();
break;
}
else
cou t < < “蛋糕没做好” << endl;
}

system("pause");
return 0;

}
结果:
蛋糕没做好

蛋糕没做好

蛋糕没做好

蛋糕没做好

蛋糕没做好

蛋糕没做好

蛋糕没做好

蛋糕没做好

蛋糕没做好

蛋糕做好了!

我来取蛋糕啦!

请按任意键继续. .

这里,我们如果想要第一时间知道蛋糕有没有做好,就必须一致查询蛋糕做没做好,换句话说,我们不能去干别的事情去了,要一直在那里等蛋糕。在程序中来看,我们的客户不停的进行查询,如果这是一个线程的话,那么这个线程在这段时间就不能继续做其他事了。.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值