C++函数指针与成员函数指针用法及表驱动实战

不晚
不晚
发布时间:2026-10-14| 2人浏览过
原创

C++函数指针分为指向普通函数的指针和指向类非静态成员函数的指针。二者在语法结构上存在显著差异:成员函数指针必须绑定特定类域,且必须显式使用取地址符赋值;调用时需配合对象实例,使用.*或->*运算符。掌握这些特性可有效替代复杂的条件分支语句,通过构建函数映射表提升代码的可扩展性与可维护性。

一、普通函数指针的基础用法

普通函数指针是指向全局函数或命名空间内函数的指针变量。与普通数据指针类似,它指向特定的内存地址(即函数代码入口)。使用函数指针前,必须确保指针声明的类型与目标函数的参数列表及返回类型完全一致。

声明一个普通函数指针的标准语法如下:

int (*pf)(int, int);  // 声明一个指向函数的指针,该函数接收两个int,返回int

此处*pf两端的括号至关重要。若省略括号写成int *pf(int, int),编译器会将此标识为一个返回值为int*的函数原型,而非指针变量。

为了避免冗长的重复声明,通常利用typedef定义函数指针类型别名。以下示例展示了定义加法与减法操作对应的函数指针,并作为参数传递调用的过程:

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

typedef int (*pFun)(int, int); // 定义类型别名

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

// 接受函数指针参数的函数
int calculate(pFun func, int a, int b) {
    return (*func)(a, b); // 解引用并调用
}

int main() {
    pFun pf = add;      // 直接赋值函数名
    cout << (*pf)(2, 3) << endl; 
    
    // 传入函数指针
    cout << calculate(sub, 8, 1) << endl;
    return 0;
}

二、类成员函数指针的声明与调用

成员函数指针与普通函数指针的核心区别在于其多态性及所属对象的依赖性。非静态成员函数隐含this指针,因此成员函数指针不仅要描述签名(签名包含参数类型、返回值),还必须锁定所属的类域。同时,成员函数指针无法像普通函数那样自动隐式转换,赋值时必须显式使用取地址符&。

第1步:正确声明与赋值成员函数指针

声明语法要求在指针变量名前加上类名::限定符。例如,针对类A的某个函数:

class A {
public:
    int add(int m, int n) { return m + n; }n};

// 声明指向A类成员函数的指针
int (A::*pmf)(int, int);

int main() {
    A obj;
    // 错误写法:pf = A::add; (编译报错)
    // 正确写法:必须显式加取地址符 &
    pmf = &A::add; 
    return 0;
}

第2步:通过对象实例调用成员函数

由于成员函数指针不依附于具体对象,在使用时必须提供对象实例。根据当前获取的是对象还是对象指针,分别使用不同的成员访问运算符:

  • 对象调用:使用(object.*pmf)(args)
  • 指针调用:使用(ptr->*pmf)(args)

以下为完整的内部接口封装示例,演示如何在类内部通过this指针调用成员函数指针:

class Calculator {
public:
    typedef int (Calculator::*MathFunc)(int, int);

    Calculator() {}

    // 内部调用方法
    int execute(MathFunc func, int a, int b) {
        return (this->*func)(a, b); // 使用 this->*
    }

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

int main() {
    Calculator calc;
    MathFunc f = &Calculator::add;
    cout << calc.execute(f, 10, 5) << endl; // 输出 15
    return 0;
}

三、基于Map的函数表驱动实现

在实际开发中,当存在大量相似功能的选择时(如计算器模式、协议解析器等),传统的if...else或switch语句会导致代码臃肿且难以维护。利用关联容器(如std::map)将操作符字符串映射到对应的成员函数指针,可以构建灵活的“函数表”,实现运行时的动态路由。

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

class TableDrivenCalc {
public:
    // 定义成员函数指针类型别名
    typedef int (TableDrivenCalc::*Operation)(int, int);

    TableDrivenCalc() {
        // 构造函数中建立映射关系
        ops["+"] = &TableDrivenCalc::add;
        ops["-"] = &TableDrivenCalc::sub;
        ops["*"] = &TableDrivenCalc::mul;
        ops["/"] = &TableDrivenCalc::div;
    }

    // 统一调用入口
    void run(string op, int a, int b) {
        auto it = ops.find(op);
        if (it != ops.end()) {
            Operation func = it->second;
            cout << (this->*func)(a, b) << endl;
        } else {
            cerr << "Unknown operator: " << op << endl;
        }
    }

private:
    map ops;

    int add(int a, int b) { return a + b; }
    int sub(int a, int b) { return a - b; }
    int mul(int a, int b) { return a * b; }
    int div(int a, int b) { return (b != 0) ? a / b : 0; }
};

int main() {
    TableDrivenCalc c;
    c.run("+", 10, 3); // 输出 13
    c.run("-", 10, 3); // 输出 7
    c.run("*", 10, 3); // 输出 30
    return 0;
}

这种模式的优点在于,如果需要增加新的计算操作(如平方根),只需添加一个新函数并在映射表中注册一行代码即可,无需修改核心控制逻辑。

四、关键注意事项总结

  1. 符号优先级:函数调用运算符()优先级高于解引用和指针访问。调用函数指针时务必加括号:(*pf)(args),调用成员函数指针时为(obj.*pf)(args)。
  2. 显式取址:成员函数指针赋值时必须写&Class::Method,不可省略&。
  3. 空指针检查:若从映射表中查找失败,应确保代码中有处理未知键值的逻辑,防止访问非法内存。

以上就是C++普通函数指针与成员函数指针的详细解析及表驱动应用的详细内容,更多关于C++高级编程技巧的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。