C面向对象
08/10
本文最后更新于
2024年08月10日,已超过
203天没有更新。如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!
五星上将麦克阿瑟曾说过:“不是C不能OOP,而是C++更有性价比”。
面向对象编程是一种编程思想,不和具体的语言工具绑定,但有些语言在语法层面支持使得面向对象编程实现更容易,比如C++,Python。
我们常说C语言是一门面向过程的语言,但实际上也可以通过C结构体、函数指针来模拟实现面向对象编程。
本文实例来自《嵌入式C语言自我修养》(王利涛编著)。
类的模拟
C语言中没有class
关键字,但可以用结构体模拟一个类(C++中类定义也可以用struct
),结构体成员类似C++类中属性,成员函数使用结构体中内嵌函数指针来模拟。
// animal.c
struct animal
{
int age;
int weight;
void (*fp)(void); //函数指针模拟成员函数
};
类似于C++的类定义
// animal.cpp
class Animal
{
public:
int age;
int weight;
void speak(void); //类方法
};
如果需要模拟类的多个方法,一个结构体中需要内嵌多个函数指针,可以将它们封装到一个结构体内。
struct func_operations
{
void (*fp1)(void);
void (*fp2)(void);
void (*fp3)(void);
void (*fp4)(void);
};
struct animal
{
int age;
int weight;
struct func_iperations fp;
};
以上就是将一个类的属性和方法封装在一个结构体里,这个结构体就相当于一个类。
继承类的模拟
通过在结构体中内嵌另一个结构体或结构体指针模拟类的继承。
struct cat
{
struct animal *p;
struct animal ani;
char sex;
void (*eat)(void); //新的成员函数
}
结构体类型cat中指针变量p指向animal结构体,就可以通过p使用结构体类型animal中属性和方法模拟类的继承。
类似于C++的继承类定义
class Cat: public Animal
{
public:
char sex;
void eat(void);
};
但毕竟C语言语法不是原生支持面向对象编程,在语法实现层面会显得繁琐。
struct cat c;
c.p = &ani; //c.p指向父类ani
c.p->fp.fp1(); //调用父类fp1函数
子类使用继承自父类的方法调用很长,如果多层继承更加繁琐。
讨论
通过前面的C实例只是想表达面向对象是一种编程思想。我们在开发应用时应该思考要解决的问题是使用面向对象实现还是面向过程实现更合适。
下表是面向过程与面向对象编程的对比(来自《C++ Software Design》)。
我们要解决的问题操作(函数、方法)集是否固定,并且是否要添加新类型(类)?
- 如果操作数量基本不变,需要通过增加类型来解决问题,那么面向对象可能更加合适。
- 但如果解决问题需要的类型不怎么增加,而是需要不断添加操作(函数),那么面向过程解决方案可能更好。
参考资料
《嵌入式C语言自我修养》(王利涛编著)

