【C语言】惊了,C语言支持面向对象编程?--函数指针结构体

1. 函数指针

函数指针是个普通指针,但是写法略不同于一般的指针

1.1 如何定义

  • 函数在结构体外定义,例:
// 原函数
int add(int a, int b) {return a + b;}
  • (重点!!)定义函数指针,例:
// 指向原函数的函数指针
int (*p)(int x, int y);

​ 可以看到,关键字:

1. 返回值类型必须相同
2. 指针变量名要用()括起来
3. 除形参名外,参数列表必须相同

  • 赋值,将指针指向函数(不要忘了这一步)

    // 直接将函数名赋值给指针
    // 函数名就是一个地址
    p = add;
    // 可以加取地址&符
    p = &add;
    

1.2 如何使用

下面三种用法是等价的:

// 直接用:指针名(实参列表)
int a = p(2, 3);
// 用定义时的写法
int b = (*p)(2, 3);
// 不用指针,这里作对照组
int c = add(2, 3);

2. 结构体

结构体实现了用户自定义数据类型,解决了基本数据类型不够用的问题

成员可以是普通的数据类型(整型、浮点型、指针、数组等),也支持结构体的嵌套

在定义结构体时不能赋值,因为结构体在没使用时是没有占内存空间,没空间用来赋值。但是在定义后有初值,为0、null或false等

例如:

typedef struct Demo {
    int x;
    int y;
}; // 不要忘记分号

3. 结构体联合函数指针

既然结构体成员可以普通指针,那么函数指针也可以作为成员

同上节的代码:

typedef struct Demo {
    int x;
    int (*p)(int x, int y);
}; // 不要忘记分号

在使用时,同其他成员一样赋值

// 在某函数中
// 1. 结构体的静态赋值:定义时顺便赋值
struct Demo demo = {1, add};

// 2. 结构体的动态复制
struct Demo demo; // 此时有默认值为0和null
demo.a = 1;
demo.p = add; // 等号右边有两种写法,参考1.1赋值
// 如果定义为结构体指针,访问成员时则用“->”符号

4. 重要应用

面向对象编程思想

面向对象是一种思想,有封装、继承、多态三个特点。高度抽象和封装,可以让应用开发者可以忽略实现的具体细节,专注于业务逻辑;代码的可重用性,让应用开发者少复制很多代码。它们不只是某些编程语言的专门特性。

C语言本身是不支持类class的,但是不乏优秀的开发者将面向对象的思想应用在C语言上面,实现起来虽然不方便,但是正是有这些思想,让开发者从C语言获得启发,开发出了更加易用和健壮的高级语言。

回调函数

函数指针变量可以作为某个函数的参数来使用的,回调函数本质就是一个通过函数指针调用的函数。

点击查看node.js异步封装与回调函数

5. 完整示例

/* 输出:
 * 5
 * 5
 * 5
 */
#include <stdio.h>

// 原函数
int add(int a, int b) { return a + b; }

int main() {
  // 定义函数指针
  int (*p)(int x, int y);

  // 两种赋值方法
  // p = add;
  p = &add;

  // 三种调用函数的方法
  printf("%d\n", p(2, 3));
  printf("%d\n", (*p)(2, 3));
  printf("%d\n", add(2, 3));
  return 0;
}
发布了12 篇原创文章 · 获赞 69 · 访问量 708

猜你喜欢

转载自blog.csdn.net/qq_33973359/article/details/105508945
今日推荐