C++普通函数指针与成员函数指针实例解析

C++的函数指针(function pointer)是通过指向函数的指针间接调用函数。相信很多人对指向一般函数的函数指针使用的比较多,而对指向类成员函数的函数指针则比较陌生。本文即对C++普通函数指针与成员函数指针进行实例解析。

一、普通函数指针

通常我们所说的函数指针指的是指向一般普通函数的指针。和其他指针一样,函数指针指向某种特定类型,所有被同一指针运用的函数必须具有相同的形参类型和返回类型。

int (*pf)(int, int);  // 声明函数指针

这里,pf指向的函数类型是int (int, int),即函数的参数是两个int型,返回值也是int型。

注:*pf两端的括号必不可少,如果不写这对括号,则pf是一个返回值为int指针的函数。

#include<iostream>
#include<string>
using namespace std; 

typedef int (*pFun)(int, int); // typedef一个类型 

int add(int a, int b){
  return a+b;
} 

int mns(int a, int b){
  return a-b;
} 

string merge(const string& s1, const string& s2){
  return s1+s2;
} 

int main()
{
  pFun pf1 = add;
  cout << (*pf1)(2,3) << endl; // 调用add函数
  pf1 = mns;
  cout << (*pf1)(8,1) << endl; // 调用mns函数
  string (*pf2)(const string&, const string&) = merge;
  cout << (*pf2)("hello ", "world") << endl; // 调用merge函数
  return 0;
}

如示例代码,直接声明函数指针变量显得冗长而烦琐,所以我们可以使用typedef定义自己的函数指针类型。另外,函数指针还可以作为函数的形参类型,实参则可以直接使用函数名。

二、成员函数指针

成员函数指针(member function pointer)是指可以指向类的非静态成员函数的指针。类的静态成员不属于任何对象,因此无须特殊的指向静态成员的指针,指向静态成员的指针与普通指针没有什么区别。与普通函数指针不同的是,成员函数指针不仅要指定目标函数的形参列表和返回类型,还必须指出成员函数所属的类。因此,我们必须在*之前添加classname::以表示当前定义的指针指向classname的成员函数:

int (A::*pf)(int, int);  // 声明一个成员函数指针

同理,这里A::*pf两端的括号也是必不可少的,如果没有这对括号,则pf是一个返回A类数据成员(int型)指针的函数。注意:和普通函数指针不同的是,在成员函数和指向该成员的指针之间不存在自动转换规则。

pf = &A::add;  // 正确:必须显式地使用取址运算符(&)
pf = A::add;  // 错误

当我们初始化一个成员函数指针时,其指向了类的某个成员函数,但并没有指定该成员所属的对象——直到使用成员函数指针时,才提供成员所属的对象。下面是一个成员函数指针的使用示例:

class A;
typedef int (A::*pClassFun)(int, int); // 成员函数指针类型 

class A{
public:
  int add(int m, int n){
    cout << m << " + " << n << " = " << m+n << endl;
    return m+n;
  }
  int mns(int m, int n){
    cout << m << " - " << n << " = " << m-n << endl;
    return m-n;
  }
  int mul(int m, int n){
    cout << m << " * " << n << " = " << m*n << endl;
    return m*n;
  }
  int dev(int m, int n){
    cout << m << " / " << n << " = " << m/n << endl;
    return m/n;
  } 

  int call(pClassFun fun, int m, int n){  // 类内部接口
    return (this->*fun)(m, n);
  }
}; 

int call(A obj, pClassFun fun, int m, int n){  // 类外部接口
  return (obj.*fun)(m, n);
} 

int main()
{
  A a;
  cout << "member function 'call':" << endl;
  a.call(&A::add, 8, 4);
  a.call(&A::mns, 8, 4);
  a.call(&A::mul, 8, 4);
  a.call(&A::dev, 8, 4);
  cout << "external function 'call':" << endl;
  call(a, &A::add, 9, 3);
  call(a, &A::mns, 9, 3);
  call(a, &A::mul, 9, 3);
  call(a, &A::dev, 9, 3);
  return 0;
}

如示例所示,我们一样可以使用typedef定义成员函数指针的类型别名。另外,我们需要留意函数指针的使用方法:对于普通函数指针,是这样使用(*pf)(arguments),因为要调用函数,必须先解引用函数指针,而函数调用运算符()的优先级较高,所以(*pf)的括号必不可少;对于成员函数指针,唯一的不同是需要在某一对象上调用函数,所以只需要加上成员访问符即可:

(obj.*pf)(arguments)     // obj 是对象
(objptr->*pf)(arguments)   // objptr是对象指针

三、函数表驱动

对于普通函数指针和指向成员函数的指针来说,一种常见的用法就是将其存入一个函数表(function table)当中。当程序需要执行某个特定的函数时,就从表中查找对应的函数指针,用该指针来调用相应的程序代码,这个就是函数指针在表驱动法中的应用。

表驱动法(Table-Driven Approach)就是用查表的方法获取信息。通常,在数据不多时可用逻辑判断语句(if…else或switch…case)来获取信息;但随着数据的增多,逻辑语句会越来越长,此时表驱动法的优势就体现出来了。

#include<iostream>
#include<string>
#include<map>
using namespace std; 

class A;
typedef int (A::*pClassFun)(int, int); 

class A{
public:
  A(){  // 构造函数,初始化表
    table["+"] = &A::add;
    table["-"] = &A::mns;
    table["*"] = &A::mul;
    table["/"] = &A::dev;
  }
  int add(int m, int n){
    cout << m << " + " << n << " = " << m+n << endl;
    return m+n;
  }
  int mns(int m, int n){
    cout << m << " - " << n << " = " << m-n << endl;
    return m-n;
  }
  int mul(int m, int n){
    cout << m << " * " << n << " = " << m*n << endl;
    return m*n;
  }
  int dev(int m, int n){
    cout << m << " / " << n << " = " << m/n << endl;
    return m/n;
  }
  // 查找表,调用相应函数
  int call(string s, int m, int n){
    return (this->*table[s])(m, n);
  }
private:
  map<string, pClassFun> table; // 函数表
}; 

// 测试
int main()
{
  A a;
  a.call("+", 8, 2);
  a.call("-", 8, 2);
  a.call("*", 8, 2);
  a.call("/", 8, 2);
  return 0;
}

上面是一个示例,示例中的“表”通过map来实现(当然也可以使用数组)。表驱动法使用时需要注意:一是如何查表,从表中读取正确的数据;二是表里存放什么,如数值或函数指针。

(0)

相关推荐

  • C++中的函数指针与函数对象的总结

    篇一.函数指针函数指针:是指向函数的指针变量,在C编译时,每一个函数都有一个入口地址,那么这个指向这个函数的函数指针便指向这个地址. 函数指针的用途是很大的,主要有两个作用:用作调用函数和做函数的参数. 函数指针的声明方法:数据类型标志符 (指针变量名) (形参列表):一般函数的声明为: int func ( int x );而一个函数指针的声明方法为:int (*func) (int x);前面的那个(*func)中括号是必要的,这会告诉编译器我们声明的是函数指针而不是声明一个具有返回型为指针

  • c++函数指针和回调函数示例

    1.函数指针 函数指针是一个指针,只是这个指针它不像普通的指针指向是是一个变量,此时它指向的是一个函数,也就是它存储的是一个函数的地址,如果我们改变它的值,让它所指向的地址由指向funA转变为指向funB,那么这个函数指针的作用就改变了. 2.回调函数 什么是回调函数呢?回调函数其实就是一个通过函数指针调用的函数!假如你把A函数的指针当作参数传给B函数,然后在B函数中通过A函数传进来的这个指针调用A函数,这就是回调机制.B函数就是回调函数. 3.函数指针的使用 3.1函数指针声明 typedef

  • c++回调之利用函数指针示例

    c++回调之利用函数指针示例 复制代码 代码如下: #include <iostream>using namespace std; /************************************************************************//*                下层实现: CALLBACK                                        *//**********************************

  • c++传递函数指针和bind的示例

    复制代码 代码如下: #include <algorithm>class TestClass{public: int Sub(int x, int y) {  return y - x; } void InitAndTest() {  PrintWithClassMemberFunction(&TestClass::Sub);  PrintWithClassPointer(this); } // call: PrintWithClassMemberFunction(&TestC

  • C++获取类的成员函数的函数指针详解及实例代码

    C++获取类的成员函数的函数指针详解 用一个实际代码来说明. class A { public: staticvoid staticmember(){cout<<"static"<<endl;} //static member void nonstatic(){cout<<"nonstatic"<<endl;} //nonstatic member virtualvoid virtualmember(){cout<

  • 详解C++中的指针、数组指针与函数指针

    C++中一个重要的特性就是指针,指针不仅具有获得地址的能力,还具有操作地址的能力.指针可以用于数组.或作为函数的参数,用来访问内存和对内存的操作,指针的使用使得C++很高效,但是指针也非常危险,使用不当会带来比较严重的问题. 1.指针 程序中所有的变量和常量都存在一个内存地址中,当然,函数也有对应的内存地址,内存地址的不同会导致程序执行时有所不同. 指针就是用来控制和存储内存地址的变量,它指向单个对象的地址,除了void之外,指针的数据类型与所指向地址的变量数据类型保持一致. 2.如何定义指针.

  • c++函数指针使用示例分享

    需求假设要设计一个名为estimate()的函数,估算编写指定行数的代码所需的时间,并且希望不同的程序员都可以使用该函数. 对于所有的用户来说,estimate()中一部分代码都是相同的,但该函数允许每个程序员提供自己的算法来估算时间. 为实现目标,采用的机制是,将程序员要使用的算法函数的地址传递给estimate(). 实现代码如下 复制代码 代码如下: // funpointer.cpp : 定义控制台应用程序的入口点.//#include "stdafx.h"#include &

  • C++基础入门教程(八):函数指针

    最近事情比较多,其实并不忙,就是事情比较影响思绪,所以都没心思写文章了. 今天主要说说函数的一些基本情况吧,同时也解释一下新手最容易迷糊的--什么时候要用指针参数? 一.函数原型和函数定义 大家都知道,C++定义函数之前,还需要声明函数原型,对于习惯Java等其他高级语言的朋友来说,真心觉得这很烦人. 如下代码: 复制代码 代码如下: // 声明函数原型 void startGame(int param); // 函数定义 void startGame(int param) {     // 各

  • C++普通函数指针与成员函数指针实例解析

    C++的函数指针(function pointer)是通过指向函数的指针间接调用函数.相信很多人对指向一般函数的函数指针使用的比较多,而对指向类成员函数的函数指针则比较陌生.本文即对C++普通函数指针与成员函数指针进行实例解析. 一.普通函数指针 通常我们所说的函数指针指的是指向一般普通函数的指针.和其他指针一样,函数指针指向某种特定类型,所有被同一指针运用的函数必须具有相同的形参类型和返回类型. int (*pf)(int, int); // 声明函数指针 这里,pf指向的函数类型是int (

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

    在Coordinate类中,有一个Display()成员函数和一个Display() const常成员函数,代码如下 class Coordinate{ public: Coordinate(int x,int y); void Display() const; void Display(); private: int m_iX; int m_iY; }; #include <iostream> #include "Coordinate.h" using namespace

  • 实例解析C++中类的成员函数指针

    C语言的指针相当的灵活方便,但也相当容易出错.许多C语言初学者,甚至C语言老鸟都很容易栽倒在C语言的指针下.但不可否认的是,指针在C语言中的位置极其重要,也许可以偏激一点的来说:没有指针的C程序不是真正的C程序. 然而C++的指针却常常给我一种束手束脚的感觉.C++比C语言有更严格的静态类型,更加强调类型安全,强调编译时检查.因此,对于C语言中最容易错用的指针,更是不能放过:C++的指针被分成数据指针,数据成员指针,函数指针,成员函数指针,而且不能随便相互转换.而且这些指针的声明格式都不一样:

  • C++编程指向成员的指针以及this指针的基本使用指南

    指向成员的指针 指向成员的指针的声明是指针声明的特例.使用以下序列来声明它们: [storage-class-specifiers] [cv-qualifiers] type-specifiers [ms-modifier] qualified-name ::* [cv-qualifiers] identifier [= & qualified-name :: member-name]; 声明说明符: 可选存储类说明符. 可选 const 和/或 volatile 说明符. 类型说明符:类型的名

  • 深入理解c++常成员函数和常对象

    先明确几个概念: 1. 常对象只能调用常成员函数. 2. 普通对象可以调用全部成员函数. 3. 当对一个对象调用成员函数时,编译程序先将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员时,由隐含使用this指针. 4. 当一个成员函数被调用时,自动向它传递一个隐含的参数,该参数是一个指向这个成员函数所在的对象的指针. 5. 在C++中,this指针被隐含地声明为: X *const this,这意味着不能给this 指针赋值: 在X类的const成员函数中,this指针的类

  • 详解C++编程中类的成员变量和成员函数的相关知识

    C++类的成员变量和成员函数 类是一种数据类型,它类似于普通的数据类型,但是又有别于普通的数据类型.类这种数据类型是一个包含成员变量和成员函数的一个集合. 类的成员变量和普通变量一样,也有数据类型和名称,占用固定长度的内存空间.但是,在定义类的时候不能对成员变量赋值,因为类只是一种数据类型,本身不占用内存空间,而变量的值则需要内存来存储. 类的成员函数也和普通函数一样,都有返回值和参数列表,它与一般函数的区别是:成员函数是一个类的成员,出现在类体中,它的作用范围由类来决定:而普通函数是独立的,作

  • C++中的四个默认成员函数与运算符重载详解

    本文主要给大家介绍了关于C++默认成员函数与运算符重载的相关内容,分享出来公的敬爱啊参考学习,话不多说,来一起看看详细的介绍: 一:类和对象的基础知识:类的定义,访问限定符,面向对象封装性,对象的大小计算等等.(编译环境为VS2015) 面向对象程序设计: 概念:(Object Oriented Programming,缩写:OOP)是一种程序设计范型,同时也是一种程序开发的方法.对象指的是类的实例,将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性.灵活性和扩展性. 类:类的基

  • C++类的空指针调用成员函数的代码

    类的实例调用成员函数的原理 其实不管是通过对象实例或指针实例调用,其实底层调用的过程都是一样的,都是把当前对象的指针作为一个参数传递给被调用的成员函数.通过下面的相关实例代码进行检验: 实验的C++代码 class Student { private: int age; public: Student() {} Student(int age) : age(age) {} int getAge() { return this->age; } }; int main(int argc, char

  • C++类中六个默认的成员函数详解

    浅谈 先来说一下"this指针": C++中通过引入this指针解决该问题,暨:C++编译器给每个"非静态的成员函数"增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问,只不过所有的操作对用户是透明的,暨用户不需要来传递,编译器自动完成. 说了这么多其实编译器在生成程序时获取对象首地址的信息.然后将获取的对象的首地址存放在了寄存器中,成员函数的其它参数都是存放在栈中.而this指针参数则是

  • C++指向类成员的指针详解

    目录 一.指向普通变量和函数的指针 二.指向类成员的指针 1.指向类数据成员的指针 2.指向类成员函数的指针 示例 总结 序言:在C++中,可以定义一个指针,使其指向类成员函数或或成员函数,然后通过指针来访问类的成员,这包括指向属性成员的指针和指向成员函数的指针. 一.指向普通变量和函数的指针 指向普通变量的指针 int a=100; int *p = &a; 指向函数的指针(即函数指针) int(*p)(int, int); 这条语句的理解:定义了一个指向函数的指针变量p,首先它是一个指针变量

随机推荐