C语言的面向对象思想

C语言的面向对象(lvgl控件面向对象的思想)

前言

C语言是一个面向过程的编程语言,并不提供面向对象的机制,但是C语言也可以按照面向对象的方式编写软件。面向对象的方式编写软件有很大的好处,一是好维护,二是好拓展,本文介绍一种C语言面向对象的写法,这个写法是从LVGL上借鉴的。

一、构建一个类,并创建对象。

首先我在person.h中,定义一个人的结构体类型:Person

typedef struct
{
	int age; //年龄
	char gender; //性别
	char name[20]; //姓名
}Person;

之后我在person.c中,写了如下一些函数,这些函数可以对Person这个类型进行修改和读取,面向对象思想中,对象有属性和方法,属性就是person结构体中的成员,方法就是如下这些函数。此时就完整的构建了一个类:人。

注:这些函数是需要在person.h中声明一下的,别的地方包含这个头文件,就可以使用这个结构体类型,调用这些函数。

int getAge(Person *p)//获取人的年龄
{
	return p->age;
}

void setAge(Person *p, int age)//设置人的年龄
{
	p->age = age;
}

char getGender(Person *p)//获取人的性别
{
	return p->gender;
}

void setGender(Person *p, char gender)//设置人的性别
{
	p->gender = gender;
}

char* getName(Person *p)//获取人的名字
{
	return p->name;
}

void setName(Person *p, char *name)//设置人的名字
{
	strcpy(p->name, name);
}

main.c中可以创建一个人,并执行人的方法。

void main()
{
	Person p;//定义了一个人的结构体局部变量,就是创建了一个人
	setName(&p,"xiaoming");//调用对象方法,设置人的名字为xiaoming
	char* name=getName(&p);//获取人的名字
	printf("%s\n",name);//打印出人的名字
}

局部变量p,执行完函数,就释放了,该p没法在函数间传递,所以还可以这样写,动态申请空间。

void main()
{
	Person *p = (Person *)malloc(sizeof(Person));//创建了一个人,空间是动态申请的。
	setName(p,"xiaoming");//调用对象方法,设置人的名字为xiaoming
	char* name=getName(p);//获取人的名字
	printf("%s\n",name);//打印出人的名字
	free(p);
}

这就是对象的创建和调用对象方法的过程。

二、对象的继承和多态

此时我想有个学生类,学生也是人,学生继承人
student.h中这样写Student结构体

typedef struct
{
	Person p;//学生继承人,关键地方是这个东西是必须要写在结构体的第一个的。
	int grade;//年级
	int class;//班级
}Student;

student.c中写几个student的几个方法

int getGrade(Student *s)//获取年级
{
	return s->grade;
}

void setGrade(Student *s, int grade)//设置年级
{
	s->grade = grade;
}

int getClass(Student *s)//获取班级
{
	return s->class;
}

void setClass(Student *s, int class)//设置班级
{
	s->class = class;
}

对象的继承和对象的多态,见如下代码

void main()
{
	Student *s=(Student*)malloc(sizeof(Student));//创建一个学生,
	setClass(s,10);//设置班级
	printf("%d\n",getClass(s));//打印学生的班级。
	
	//学生继承人,面向对象中,子类是继承父类的方法和属性。
	//学生可以调用父类的方法,调用父类方法时,参数类型不一样,只需强转一下就好。
	setName((Person *)s, "xiaoming");//调用父类的方法,设置学生的名字为xiaoming
	char* name=getName((Person *)s);//调用父类方法,读出学生的名字
	printf("%s\n",name);//打印名字

	//可以看到,上面的执行,可以顺利设置名字和打印名字。
	printf("%s\n",s->p.name);//用这种朴素方式打印一下,也是上面设置的正确的名字。
}

可以看到,学生可以完全不受影响的调用人的所有函数,功能逻辑也是正常。这样看,学生就是人,可以调用人的函数,并且它在人的基础上加了两个属性,还多了一些方法。
比如你用C做UI,开发了一个控件,后面想基于这个控件功能之上,再开发一个新的控件,我就可以用这个方式,新的控件完完全全可以直接调用之前控件的所有函数,行为逻辑一模一样,并且在此基础上还有自己新增的一些功能,这种方式不仅实现了功能的拓展,不存在重复代码,还使得代码更加的利于维护,更加的优雅。

三、总结

这个案例,学生继承人,学生的结构体中必须有人,这个人不是指针,就是人的变量,且这个人,必须放在学生成员的第一位。这样就可以实现学生能随便的调用人的函数。子类继承父类的方法。
学生还能再往下继承,比如中学生继承学生,中学生还有各科的成绩的属性。中学生结构体中第一个成员就是学生,后面是成绩,中学生可以调用学生的函数,也能调用人的函数。还有各科的成绩的拓展,多重继承,厉害吧。
这个面向对象的方式就是LVGL控件继承的思想,它只能单继承。其实利用的是结构体成员变量的地址偏移位置相同的原理,它非常巧妙,能让你的代码更加简单优雅,利于维护,少加班。
如果觉得我这个博客有意义的话,点赞并收藏,感谢您的支持!

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值