65.9K
CodeProject 正在变化。 阅读更多。
Home

函数指针的面向对象包装器

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.89/5 (13投票s)

2004 年 9 月 9 日

2分钟阅读

viewsIcon

71730

downloadIcon

395

函数指针为一阶函数提供了一个方便的机制,但在使用上相当复杂。 本文给出了这些函数指针的包装器,使它们的使用更容易。

引言

有时函数仅在您无法使用变量表达的几个方面有所不同,您真正喜欢做的是传递一个可以处理“特殊”情况并保持抽象性的函数。 在某些语言(如Scheme)中,您可以将函数作为参数传递; 在C++中,您必须使用函数指针。

函数指针对于C来说是一个很好的系统,但不适用于C++;您必须定义一个非类成员或静态类成员……因此,如果不使用全局变量,我们将无法访问类的非静态数据成员。

解决方案是创建一个函数指针的包装器,其中包含函数指针和指向类的指针。

注意:STL使用的另一种替代方法是函数对象; 我不喜欢这种方法,因为它会导致太多的类型工作 ;)。

用法

我将描述一个关于如何合并/使用函数指针包装器的简短指南。

  1. 将以下语句添加到您的头文件
    ...
    #include "functor.h"
    ...
  2. (可选) 对模板化函数指针执行 typedef,这使得它更容易阅读:)。

    建议在您的类定义中进行此typedef,以防止污染您的全局命名空间。 我通常将它们放在类的私有声明中。

    typedef Functor<Test, void, int> Function;

    在此示例中,Test是包含该函数的类,void是函数的返回值,int是函数的唯一参数。

  3. 定义你的类,我在这里添加了一个快速的类示例
    /* 
     * header file
     */
    class Test
    {
    public:
      void TestFunc();
    
    private:
      void Add(int x);
      void Mul(int x);
      void DoSomething(int x, Function f);
    
      int value_;
    };
    
    /* 
     * source file
     */
    void Test::Add(int x)
    {
      value_ += x;
    }
    
    void Test::Mul(int x)
    {
      value_ *= x;
    }
    
    void Test::DoSomething(int x, Function f)
    {
      // some very complicated code
      ...
      f(x);
      ...
      // lots of other code
    }

    在示例中,您应该注意f(x),这是函数指针包装器的调用。 看起来完全像一个常规函数调用,但是f是函数的参数。

  4. 创建函数指针包装器
    void Test::TestFunc()
    {
      // create the function pointer wrapper (functor)
      Function myadd(this, &Test::Add);
      Function mymul(this, &Test::Mul);
    
      // now do the action!
      DoSomething(5, myadd);
    }

    您只需将两个参数传递给构造函数即可创建一个包装器对象:函数的主机类(通常是this)和包装器应使用的方法名称。

    现在您可以将该函数传递给任何方法,并像调用普通函数一样调用它:)

技术资料

包装器的系统基于模板和运算符重载的使用。 模板用于使其更通用(即,能够为具有指定数量参数的任何函数创建包装器)。 运算符重载用于模拟常规的过程调用,我们重载operator()来实现此目的。

已知限制

源代码仅包含一个和两个参数的包装器。 如果您需要更多,则需要扩展类或传递包含数据的struct/class作为单个参数。

待办事项

  • const成员函数的兼容性
  • 创建一个示例项目
  • 创建一个内联版本,与VC++ 6或更低版本兼容。

历史

  • 1.0.1版 - 2004年9月12日

    根据Roland Pibinger和KevinHall的建议进行了一些更正。 谢谢!

  • 1.0.0版 - 2004年9月9日

    初始发布。

© . All rights reserved.