您的位置:逆风者 VC++ 正文
 添加时间:2007-09-01 原文发表:2007-08-31 人气:43 来源:vckbase.com

本文章共5959字,分4页,当前第2页,快速翻页:
 
for_each(m_clients.begin(), m_clients.end(),

NotifyProgress(nFound));

  for_each 算法从头到尾迭代容器元素,并对每个元素调用函数对象 NotifyProgress。这里说的“函数对象”到底是指的什么呢?不是一个函数,它是一个对象。这个类看起来像下面这个样子:
逆风编程精品


class NotifyProgress {

protected:

  UINT m_nFound;

public:

  NotifyProgress(UINT n) : nFound(n) { }

  void operator()(IPrimeEvents* obj)

  {

    obj->OnProgress(nFound);

  }

};	
  NotifyProgress 实现函数 operator()(IPrimeEvents*),它是 for_each 算法需要的东西。一般来讲,如果你具备一个类型为 T 对象集合,for_each 会需要一个实现 operator()(T) 的仿函数(functor)。它调用该集合中 T 对象的这个操作符。所以这里函数 operator 有一个 IPrimeEvents 指针参数并返回 void —— 因为客户机列表是一个 IPrimeEvents 指针列表。为了传递附加参数,构造函数将它们保存在数据成员里。NotifyProgress(nFound) 调用构造函数以创建一个用 m_nFound=nFound 初始化的堆栈实例。所以,任何触发 Foo 事件的 Foo 仿函数的一般模式是这样的:

class NotifyFoo {

protected:

  ARG1 m_arg1; // whatever, as many as needed

public:

  NotifyProgress(ARG1 a1, ...) : m_arg1(a1) { }

  void operator()(IMyEvents* obj)

  {

    obj->OnFoo(m_arg1, ...);

  }

};	
  构造函数将事件参数作为数据成员来保存,函数 operator 将它们传递到对象事件处理函数。对于所有仿函数来说,最终结果是——将函数 OnFoo 转换为类 NotifyFoo。这样做为什么会有用呢?因为我能编写一个模板。在我开始做之前,有一件事我必须得提一下。那就是你必须从一个叫 unary_function 的 STL 类派生你的仿函数类:

class NotifyProgress : 

  public unary_function 

{

  .

  . // as before

  .

};	
  也就是说,NotifyProgress 是一个一元函数,其函数 operator 带一个参数,IPrimeEvents 指针并返回 void。该一元函数使你的仿函数类“可适配”,使你能将它与 STL 适配器,如:not1、bind2nd 等等进行结合。但是即使你从来都没有打算使用适配器,就像我的事件处理例程,unary_function 仍然不失为一个好主意,因为它向这个世界宣告:“这是一个函数类。”它是一种将代码文档化的方式。有关适配器的详细讨论,参见 Effective STL:50 Specific Ways to Improve Your Use of the Standard Template Library (Addison-Wesley, 2001) by Scott Meyers
  STL 的高手们也许会问:为什么我不使用 mem_fun 适配器直接将 IPrimeEvents::OnProgress 转换为函数对象。因为 OnProgress 是虚拟函数,我不能适配一个虚拟函数。如果这样做,要触及到基类。如果你使用 Boost 库,可以用其捆绑适配器直接将 OnFoo 这样的虚拟事件处理器转换为仿函数,不用编写仿函数。如果你不明白我所讲的这些内容,不用害怕,不看这些内容好了。
  当然,我还需要一个 Done 事件的 NotifyDone。由于 Done 没有参数,构造函数也没有:

class NotifyDone : public unary_function 

{

public:

  NotifyDone() { }

  void operator()(IPrimeEvents* obj)

  {

    obj->OnDone();

  }

};	
  现在我有了自己的仿函数类,我可以用 for_each 代替手工迭代客户机列表。可我把它们放在哪呢?仿函数属于与事件说明有关的范畴,所以我把它们放在 IPrimeEvents 接口中,用嵌套类的形式。代码如 Figure 2 所示。细心的读者会注意到我在两个地方还做了细小的恶修改。仿函数的命名没有用 NotifyProgress,而是叫做 Progress。稍后你会明白这样做使代码更易读;还有就是我没有把事件处理器都声明为纯虚拟函数,而是将它们定义为空实现。IPrimeEvents 只有两个事件,但对于一般的事件机制来说,如果程序员感兴趣的的处理并不多,但要让他们实现每一个事件处理器似乎不是很友好。所以这里每个处理器默认实现什么也不做。为了使基类抽象化,我声明了一个纯虚拟析构函数。当你想抽象化一个没有任何纯虚函数的基类时,这是一个标准的C 技巧。唯一的要做的是你必须定义一个析构函数。纯虚拟函数没有定义——除非它是析构函数。既然每一个派生类的析构都调用其基类的析构函数,那么基类需要一个实现,即便它是纯虚拟的:
 
本文章更多内容<<上一页 - 1 - 2 - 3 - 4 - 下一页>>
相关文章

用鼠标手势动作来发送命令
在VC中使用 Flash 美化你的程序
更改屏幕显示数据的作弊程序
通过串口收发短消息(上)
C 程序的外部变量与函数
如何用代码动态添加控件
一个关于#include的问题
使用免费界面换肤软件 USkin
把 C# 语言开发的控件内嵌在网页里面
支持数据项查找功能的树控制(CTreeCtrl)类
浅谈PDFlib中文输出(四)PDFlib 接收的几种
后缀表达式求值及校验
用ATL开发复合控件
关于 IDispatch 接口的 LPDispatch 属性的实
获得 Win32 窗口句柄的更好的方法
从 ADO 迁移到 ADO.NET(一)
利用VC++开发ASP图像处理组件(二)
可设置单元格颜色的ClistCtrl类
IP Messenger 详细分析
C :使用 Visual C 2005 的现代语言特色

相关评论


本文章所属分类:首页 VC++

  热门关键字: