`
hcmfys
  • 浏览: 356302 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

类成员函数指针浅析

    博客分类:
  • c++
阅读更多

有这样一行代码:
  typedef CPB_RETVAL (CPBprb_Prb::*CPBprb_action)(CPBprb_Prb &, unsigned);
  其中CPB_RETVAL是一个enum类型,CPBprb_Prb是一个类,CPBprb_action在代码中其他地方没有找到定义。因不知这行代码所为何意,  

 承蒙众多高手赐教,才知上段代码定义了成员函数指针类型CPBprb_action,该类型函数有2个参数,

类型分别为CPBprb_Prb &, unsigned,返回值类型为CPB_RETVAL。此函数指针的类型有个定义域,它是类CPBprb_Prb的成员(CPBprb_Prb::*CPBprb_action)。
  另外,CPBprb_action不仅可以指向CPBprb_Prb的成员函数,也可以指向CPBprb_Prb的派生类成员函数。甚至,CPBprb_Prb里可以根本就没有任何诸如CPB_RETVAL functionName (CPBprb_Prb &, unsigned)这样的函数,而完全可以在CPBprb_Prb的派生类里去增加 CPB_RETVAL functionName (CPBprb_Prb &, unsigned);这样的函数,如:
  

#include 
  class A
  {
  public:
  A(){};
  virtual ~A(){};
  };
  class B : public A
  {
  public:
  B(){};
  ~B(){};
  int Fb(int a){ return a*a;}
  };
  typedef int (A::*Myfunction)(int);
  int main()
  {
  B* pB = new B;
  Myfunction pf = (Myfunction)(&B::Fb);
  int retValue = (pB->*pf)(3);
  std::cout<  std::cin>>retValue;
  return 1;
  }

   通过typedef int (A::*Myfunction)(int);定义的Myfunction是A的成员(函数指针),但只能在类外定义。
  需要指出的是,使用指向成员函数的指针变量是比较危险的!因此不建议这么用。
  (上文引用了论坛中对我帖子的回复,再次对关心并帮助我的人表示感谢。)
  PS:
  函数指针(全局函数/类成员函数)和函数对象
  (原文链接:http://www.ccrun.com/article.asp?i=1005&d=sc37og)
  关键字:函数指针 全局函数 类成员函数 函数对象 Function object
  作者:ErranLi 更新:2007-01-06 02:31:47 浏览:9166
  函数指针(全局函数/类成员函数)、函数对象(Function object)

 一. 函数指针类型为全局函数.

  #include "stdafx.h"
  #include 
  using namespace std;
  class TestAction;
  typedef void (*fp)(int);
  void Drink(int i)
  {
  cout<<"No. "<  }
  void Eat(int i)
  {
  cout<<"No. "<  }
  class TestAction
  {
  public:
  fp testAct;
  void TestAct(int i)
  {
  if (testAct != NULL)
  {
  testAct(i);
  }
  }
  };
  int main(int argc, char* argv[])
  {
  TestAction doact;
  doact.testAct = &Drink;
  doact.TestAct(0);
  doact.TestAct(1);
  doact.TestAct(2);
  doact.testAct = &Eat;
  doact.TestAct(0);
  doact.TestAct(1);
  doact.TestAct(2);
  return 0;
  } 

  

二. 函数指针类型为类成员函数.
  

#include "stdafx.h"
  #include 
  using namespace std;
  class Action;
  class TestAction;
  // 函数指针类型为类 Action 的成员函数
  typedef void (Action::*fp)(int);
  class Action
  {
  public:
  void Drink(int i)
  {
  cout<<"No. "<  }
  void Eat(int i)
  {
  cout<<"No. "<  }
  };
  class TestAction
  {
  public:
  // 定义一个函数指针
  fp testAct;
  //Action 对象实例 , 该指针用于记录被实例化的 Action 对象
  Action * pAction;
  void TestAct(int i)
  {
  if ((pAction != NULL) && (testAct != NULL))
  {
  // 调用
  (pAction->*testAct)(i);
  }
  }
  };
  int main(int argc, char* argv[])
  {
  Action act;
  TestAction doact;
  doact.pAction = &act;
  doact.testAct = &Action::Drink;
  doact.TestAct(0);
  doact.TestAct(1);
  doact.TestAct(2);
  doact.testAct = &Action::Eat;
  doact.TestAct(0);
  doact.TestAct(1);
  doact.TestAct(2);
  return 0;
  } 

   三. 函数对象 (Function object)
  // 本文转自 C++Builder研究 - http://www.ccrun.com/article.asp?i=1005&d=sc37og
  

#include "stdafx.h"
  #include 
  #include 
  using namespace std;
  class Action;
  class Drink;
  class Eat;
  class TestAction;
  class Action
  {
  public:
  int operator()(int i)
  {
  Act(i);
  return i;
  }
  virtual void Act(int i) = 0;
  };
  class Drink : public Action
  {
  void Act(int i)
  {
  cout<<"No. "<  }
  };
  class Eat : public Action
  {
  void Act(int i)
  {
  cout<<"No. "<  }
  };
  class TestAction
  {
  public:
  void TestAct(int i, Action& testAct)
  {
  testAct(i);
  }
  };
  int main(int argc, char* argv[])
  {
  TestAction doact;
  doact.TestAct(0, Drink());
  doact.TestAct(1, Drink());
  doact.TestAct(2, Drink());
  doact.TestAct(0, Eat());
  doact.TestAct(1, Eat());
  doact.TestAct(2, Eat());
  return 0;
  } 

 

虽然传递函数指针被广泛应用于事件驱动系统中,以此实现回调函数通过指针来调用。但 C++ 还是提供了另外一种可供选择的办法,即函数对象,利用它可以避免使用函数指针。这样做有几个优点。首先, 因为对象可以在内部修改而不用改动外部接口,因此设计更灵活,更富有弹性。函数对象也具备有存储先前调用结果的数据成员。。 此外,编译器可以内联函数对象,从而进一步增强性能。函数对象可以具体表达依赖成员模板的通用算法 , 这些算法借助普通的函数指针难以完成。例用函数对象实现了一个通用的 Negation 算法操作:
 

#include "stdafx.h"
  #include 
  using namespace std;
  class Negate
  {
  public:
  template T operator()(T t) const
  {
  return -t;
  }
  };
  void Callback(int n, const Negate& neg) // 传递一个函数对象
  {
  n = neg(n); // 调用重载的 () 操作 来对 n 进行 negate 操作
  cout << n << endl;
  }
  int main(int argc, char* argv[])
  {
  // 调用方式一
  Callback(5, Negate());
  // 调用方式二
  Negate neg;
  cout << neg(9.99999) << endl;
  cout << neg(__int32(39999999)) << endl;
  return 0;
  }

  

  STL 库中定义了很多函数对象以供相关算法调用,如 模板化的函数对象 greater<> 或者 less<>:
  vector vi;
  //.. 填充向量
  sort(vi.begin(), vi.end(), greater() );// 降序 (descending)
  sort(vi.begin(), vi.end(), less() ); // 升序 (ascending)
  本文转自:http://www.cppblog.com/erran/archive/2006/12/26/16868.html
  函数对象(function object),又名仿函数(functor),是重载了operator()的一个类,其实在stl算法中有大量运用,c++标准预定义的如 less <>,greater <>,bind2nd <>等
  为什么引入仿函数?
  原因:
  1.仿函数有具体型别,可用在模板参数,而函数不行
  2.同类仿函数可有不同植,可代表不同状态,比函数灵活(须定义多个)
  3.仿函数可能比普通函数快 

 

分享到:
评论

相关推荐

    浅析成员函数和常成员函数的调用

    成员函数和常成员函数是C++中面向对象编程的重要概念,它们在类的定义和对象的使用中扮演着关键角色。本文将详细解析这两种函数的调用方式及其区别。 成员函数是类的一部分,用于实现类的功能。它们可以直接访问类...

    浅析C++类的底层实现

    类定义了对象的属性(成员变量)和行为(成员函数),通过权限控制(如private和public)来保护数据,防止外部随意访问和修改,从而实现信息隐藏,增强程序的安全性。 类的定义包括了成员变量和成员函数。例如,一...

    Delphi类与对象内存结构浅析

    ### Delphi类与对象内存结构浅析 #### 一、Delphi类与对象的基本概念 在探讨Delphi类与对象的内存结构之前,我们需要先理解一些基本的概念。 **静态内存与动态内存:** - **静态内存**:指的是程序运行前就已经...

    浅析C++中的虚函数

    用途:实现多态性,通过指向派生类的基类指针,访问派生类中同名覆盖成员函数 虚函数必须是基类的非静态成员函数,其访问权限可以是protected或public。 定义为virtual的函数是基类期待派生类重新定义的,基类希望...

    「漏洞分析」以太坊Solidity未初始化存储指针安全风险浅析 - web安全.zip

    4. **重入攻击**:在某些情况下,未初始化的存储指针可能与重入攻击相结合,攻击者可以利用此漏洞多次调用合约的敏感函数,导致资金被无限次转移。 为了预防这些风险,开发者应遵循以下最佳实践: 1. **初始化变量...

    内存分配器dlmalloc2.8.3源码浅析

    ### 内存分配器dlmalloc2.8.3源码浅析 #### 1. 边界标记法 dlmalloc采用边界标记法对内存进行高效管理。这种方法通过将可用内存分割成一系列固定大小的块(chunk),每个块都有特定的头部和尾部信息用于追踪其状态...

    ASP.NET笔试题浅析

    - 委托是类型安全的函数指针,用于将方法作为参数传递。 - 事件是委托的一种特殊形式,用于实现发布-订阅模式,允许对象间通信而不直接暴露方法。 13. **Override与Overload**: - `override`用于重写基类的虚...

    浅析C++的特殊工具与技术

    成员函数指针允许我们传递函数作为参数,或者存储为其他类型的数据。使用成员指针时,可以使用`.`或`-&gt;`操作符来访问对象的成员,这在实现回调机制或者设计模式(如策略模式)时非常有用。 最后,嵌套类是C++中一个...

    深入浅析C++多态性与虚函数

    如果派生类没有改写继承基类的虚函数,则函数指针将调用基类的虚函数。 三、静态联编和动态联编 3.1 静态联编 静态联编是在编译阶段就将函数实现与函数调用绑定起来。静态联编在编译阶段就必须了解所有函数与模块...

    浅析C++构造函数虚拟化

    由于构造函数本身不支持虚拟调用,readComponent函数通过一个静态成员函数或辅助函数间接实现了类似构造函数的功能,因此称为虚拟构造函数。 除了虚拟构造函数,还有虚拟拷贝构造函数。这种特殊的构造函数能够返回...

    C++的效率浅析文档

    - **普通成员函数**:非内联且非虚的成员函数调用与C语言的函数调用类似,具有相对较低的开销。 2. **对象创建与销毁**: - **构造函数与析构函数**:C++中的构造函数在对象创建时执行初始化,析构函数在对象销毁...

    C++中常见内存错误及对策浅析

    ### C++中常见内存错误及对策浅析 #### 一、引言 C++作为一种强大的面向对象编程语言,因其灵活性而被广泛应用于多种领域。然而,C++的强大特性也带来了诸多挑战,尤其是在内存管理方面。动态内存管理允许程序员在...

    深入浅析STL vector用法

    这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作。本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和for_each()中的使用。通过阅读这篇文章读者应该能够有效地使用...

    浅析C++ new的三种面貌

    当为类成员函数时,使用 new 产生类对象时调用的则是其成员函数 operator new()。如果要重载全局的 operator new,会改变所有默认的 operator new 的方式,所以必须要注意。 3. placement new() placement new() ...

    浅析c++ 中const关键字

    又例如,在编写类时,我们可以使用const关键字来确保类成员的安全性。 const关键字是一个强大的工具,它可以帮助我们编写更加安全、可靠的程序。我们应该充分利用const关键字来提高程序的安全性和可靠性。

    浅析面向对象语言C_与Java区别_王艳娟1

    C++不仅支持成员函数运算符重载,还支持友元函数的重载,可以直接实现对象间的四则运算。 6. **原型声明**:Java中无需提前声明就能使用类或方法;C++则必须先定义或进行原型声明。 7. **预处理**:Java没有预处理...

    通信笔试宝典v3a(139页)

    - 高级用法:指针数组、函数指针等。 - **作用域问题** - 变量的作用域决定了变量的可见性和生命周期。C语言中有全局作用域、局部作用域和文件作用域等。 **1.2 高质量的C/C++代码** - 编写高质量代码的原则...

    深入浅析c/c++ 中的static关键字

    静态成员方法是一种特殊的成员方法,它不需要this指针,也就是说,不需要通过对象来调用静态成员方法。静态成员方法可以调用非静态成员方法,但非静态成员方法不能调用静态成员方法。 三、静态成员变量的初始化 ...

Global site tag (gtag.js) - Google Analytics