C语言学习细节|C语言面向对象编程!函数指针如何正确使用

admin2024-05-15  1

文章目录

  • 1.函数指针定义
  • 2.格式
  • 3.应用
    • 回调函数
    • 动态函数调用
    • 函数的间接调用
  • 4.结构体与函数指针结合

1.函数指针定义

函数指针就是一个指向函数的指针变量,与指向数据的指针不同,函数指针保存的是函数的地址,这使得程序可以动态地调用不同的函数,而无需在编译时确定具体的函数。可以在程序运行时动态得传递和调用不同的函数

2.格式

函数指针的声明格式为:

返回类型(*变量名)(参数列表),其中

例如,如果你有一个返回 int 类型并接受两个 int 类型参数的函数,你可以这样声明指向这种函数的指针:

int (*funcPtr)(int, int);

3.应用

函数指针在C语言中扮演着极其重要的角色,特别是在需要动态决定函数调用时。下面是三个具体的应用场景:

回调函数

在C语言中,回调函数通常用于实现基于事件的编程。例如,在一个图形用户界面库中,可能需要允许用户定义当按钮被点击时执行的动作。以下是一个简单的例子,展示了如何在一个假设的GUI库中使用回调函数来处理按钮点击事件:

#include <stdio.h>

//定义函数指针
typedef void (*ButtonClickHandler)();

//定义Button结构体
typedef struct Button {
    char* label; //函数名
    ButtonClickHandler onClick; //回调函数
} Button;

//绑定回调函数
void buttonClick(Button* button) {
    if (button->onClick != NULL) {
        printf("Button '%s' clicked.\n", button->label);
        button->onClick();
    }
}

//具体执行的函数
void handleExit() {
    printf("Exiting application...\n");
}

int main() {
    Button exitButton = {"Exit", handleExit};
    buttonClick(&exitButton);
    return 0;
}

在这个例子中,Button 结构体包含了一个成员 onClick,这是一个指向函数的指针。当按钮被“点击”时(在这个例子中是通过调用 buttonClick 函数模拟),如果设置了 onClick 回调,它就会被调用。

动态函数调用

函数指针允许根据程序的状态或用户的输入动态调用不同的函数。例如,在一个简单的命令行计算器应用中,用户的选择可以决定调用哪个数学运算函数:

#include <stdio.h>

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

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

int main() {
    int (*operation)(int, int);
    char operator;
    int x = 5, y = 3;

    printf("Enter operation (+ or -): ");
    scanf(" %c", &operator);

    switch (operator) {
        case '+':
            operation = add;
            break;
        case '-':
            operation = subtract;
            break;
        default:
            printf("Invalid operation\n");
            return 1;
    }

    printf("Result: %d\n", operation(x, y));
    return 0;
}

函数的间接调用

函数的间接调用通常用于实现插件架构,其中函数可以在运行时加载和调用。在下面的例子中,我们模拟这种结构,其中函数指针数组用于调用一系列操作:

#include <stdio.h>

void start() {
    printf("Starting the engine...\n");
}

void stop() {
    printf("Stopping the engine...\n");
}

void restart() {
    printf("Restarting the engine...\n");
}

int main() {
    void (*operations[3])() = {start, stop, restart};

    for (int i = 0; i < 3; i++) {
        operations[i]();
    }

    return 0;
}

在这个例子中,我们定义了一个函数指针数组 operations,其中包含三个不同的操作:启动、停止和重启。通过遍历数组,我们可以间接调用这些函数。

4.结构体与函数指针结合

在C语言中,结构体与函数指针结合使用可以模拟面向对象编程中的类和方法。结构体可以包含指向函数的指针,允许结构体"实例"具有操作这些数据的"方法"。这是实现模块化和封装设计的一种方式。

例如,可以定义一个表示几何形状的结构体,该结构体包括函数指针,用于计算面积和周长:

typedef struct Shape {
    int (*getArea)(struct Shape*);
    int (*getPerimeter)(struct Shape*);
    int width;
    int height;
} Shape;

int rectangleArea(Shape* s) {
    return s->width * s->height;
}

int rectanglePerimeter(Shape* s) {
    return 2 * (s->width + s->height);
}

void createRectangle(Shape *s, int width, int height) {
    s->width = width;
    s->height = height;
    s->getArea = rectangleArea;
    s->getPerimeter = rectanglePerimeter;
}

int main() {
    Shape rect;
    createRectangle(&rect, 5, 10);
    printf("Area: %d\n", rect.getArea(&rect));
    printf("Perimeter: %d\n", rect.getPerimeter(&rect));
    return 0;
}

在这个例子中,Shape 结构体模仿了一个简单的"类",其中包含数据成员(宽度和高度)和作为其"方法"的函数指针。这种方式在设计需要封装数据和功能的模块时非常有用。

文章结构上参考了B站up主:【五分钟解决方案】函数指针如何正确使用
算是终于弄明白了函数指针了,至于指针函数,就把它理解为返回一个指针的函数,其实和别的函数没有任何区别,唯一需要注意的就是别返回一个临时变量的指针即可。
在一个在C++中往往会使用function和bind来实现,代码更加简洁优雅直观
扩展阅读:
C++语法|可调用对象与function类型
C++语法|bind和function解析并实现一个简易线程池
C++语法|bind1st和bind2nd的用法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明原文出处。如若内容造成侵权/违法违规/事实不符,请联系SD编程学习网:675289112@qq.com进行投诉反馈,一经查实,立即删除!