面向对象和面向过程的基本概念
面向对象和面向过程是两种不同的编程范式,它们在软件开发中用于组织和设计代码的方式。
面向过程编程(Procedural Programming)是一种以过程(函数、方法)为核心的编程方式。在面向过程编程中,程序被划分为一系列的过程或函数,这些过程按照顺序逐步执行,每个过程都可以接受输入参数并返回输出结果。数据在过程中被操作,通过参数进行传递。面向过程编程关注的是解决问题的步骤和算法,通过将问题拆分为一系列的步骤来解决。
面向对象编程(Object-Oriented Programming,OOP)是一种以对象为核心的编程方式。在面向对象编程中,程序被组织成一系列的对象,每个对象都有自己的属性(数据)和行为(方法)。对象之间通过消息传递来进行通信和交互,对象可以通过继承、封装和多态等特性进行关联和扩展。面向对象编程关注的是将现实世界中的事物抽象成对象,通过对象之间的交互来解决问题。
面向过程和面向对象的主要区别如下:
当我们具体分析面向过程和面向对象编程时,可以从以下几个方面进行比较:
一下的代码是使用面向过程的思维进行编写的
#include
#include
#include
/*
面向过程和面向对象
question1: 面向过程 1: 将问题的解法分解成若干步骤 2: 使用函数分别实现这些步骤 3: 依次调用这些函数
question2: 面向对象 1: 面向对象的编程逻辑使用c语言实现面向对象的过程
面向对象编程风格的三大特性 1: 封装 2: 继承 3: 多态
*/
// 创建学生类型的结构体
struct student {
int id;
char name[20];
int gender;
int mark;
};
// 学生的学号
int makeStudentId(int year, int classNum, int serialNum) {
char buffer[20];
// sprintf的作用是字符拼接,将结构传入第一个参数buffer指示的字符当中
sprintf(buffer, "%d%d%d", year, classNum, serialNum);
// 函数atoi将指示的字符串转换为整型并返回结果
int id = atoi(buffer);
return id;
}
// 定义性别的结构体0表示为女生, 1 表示为男生,定义两个函数对性别进行处理将整型表示的性别转换为字符串表示的性别
const char* numGenderToStrGender(int numGender) {
if (numGender == 0) {
return "女";
}
else if (numGender == 1) {
return "男";
}
return "佚名";
}
// 将字符串表示的性别转换为整型表示的性别进行处理
int strGenderToNumGender(const char* strGender) {
int numGender;
if (strcmp("男", strGender) == 0) {
numGender = 1;
}
else if (strcmp("女", strGender) == 0) {
numGender = 0;
}
else {
numGender = -1;
}
return numGender;
}
int main(){
// 结构体的声明
struct student stu;
// 给id赋值
stu.id = makeStudentId(2022, 607, 12);
// 给name赋值
strcpy(stu.name, "小明");
// 给gender赋值
stu.gender = strGenderToNumGender("男");
// 直接给mark赋值
stu.mark = 98;
// 使用printf打印输出相关数据,采用点的方式对函数进行调用
printf("学号:%d\n", stu.id);
printf("姓名:%d\n", stu.name);
// 将数字1和0转换为字符串男和女
const char* gender = numGenderToStrGender(stu.gender);
printf("性别%d\n", gender);
printf("分数%d\n", stu.mark);
return 0;
}
面向对象代码的编写方式
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
// 编写函数指针
struct student {
void (*setStudentId)(struct student* s, int year, int classNum, int serialNum);
const char* (*getGender)(struct student* s);
void (*setGender)(struct student* s, const char* strGender);
int id;
char name[20];
int gender;
int mark;
};
// 学生的学号
void setStudentId(struct student *s,int year, int classNum, int serialNum) {
char buffer[20];
// sprintf的作用是字符拼接,将结构传入第一个参数buffer指示的字符当中
sprintf(buffer, "%d%d%d", year, classNum, serialNum);
// 函数atoi将指示的字符串转换为整型并返回结果
int id = atoi(buffer);
// 使用面向对象的方式直接给结构体中的成员id赋值
s->id = id;
}
const char* getGender(struct student *s) {
if (s->gender == 0) {
return "女";
}
else if (s -> gender == 1) {
return "男";
}
return "佚名";
}
// 将字符串表示的性别转换为整型表示的性别进行处理
void setGender(struct student* s, const char* strGender) {
int numGender;
if (strcmp("男", strGender) == 0) {
numGender = 1;
}
else if (strcmp("女", strGender) == 0) {
numGender = 0;
}
else {
numGender = -1;
}
s ->gender = numGender;
}
// 初始化方法
void initStudent(struct student* s)
{
s->setStudentId = setStudentId;
s->getGender = getGender;
s->setGender = setGender;
}
int main(){
// 结构体的声明
struct student stu;
// 函数体在使用过程中需要调用initStudent函数设置正确的指向
initStudent(&stu);
// 直接调用函数传入结构体指针
setStudentId(&stu, 2023, 607, 12);
strcpy(stu.name, "小明");
setGender(&stu, "男");
stu.mark = 98;
// 使用printf打印输出相关数据,采用点的方式对函数进行调用
printf("学号:%d\n", stu.id);
printf("姓名:%s\n", stu.name);
// 将数字1和0转换为字符串男和女
const char* gender = stu.getGender(&stu);
printf("性别%s\n", gender);
printf("分数%d\n", stu.mark);
return 0;
}
面向对象继承方面的代码
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
// 编写函数指针
// 继承
struct person {
int id;
char name[20];
int gender;
const char* (*getGender)(struct person* s);
void (*setGender)(struct person* s, const char* strGender);
};
struct teacher {
struct person super;
char subject[20];
};
struct student {
struct person super;
int mark;
void (*setStudentId)(struct student* s, int year, int classNum, int serialNum);
};
// 学生的学号
void setStudentId(struct student *s,int year, int classNum, int serialNum) {
char buffer[20];
// sprintf的作用是字符拼接,将结构传入第一个参数buffer指示的字符当中
sprintf(buffer, "%d%d%d", year, classNum, serialNum);
// 函数atoi将指示的字符串转换为整型并返回结果
int id = atoi(buffer);
// 使用面向对象的方式直接给结构体中的成员id赋值
s->super.id = id;
}
const char* getGender(struct person *s) {
if (s->gender == 0) {
return "女";
}
else if (s -> gender == 1) {
return "男";
}
return "佚名";
}
// 将字符串表示的性别转换为整型表示的性别进行处理
void setGender(struct person* s, const char* strGender) {
int numGender;
if (strcmp("男", strGender) == 0) {
numGender = 1;
}
else if (strcmp("女", strGender) == 0) {
numGender = 0;
}
else {
numGender = -1;
}
s ->gender = numGender;
}
// 初始化函数指针
void initPerson(struct person* p) {
p->getGender = getGender;
p->setGender = setGender;
}
// 初始化函数
void initStudent(struct student* s) {
initPerson(&(s->super));
s->setStudentId = setStudentId;
}
// 初始化函数
void initTeacher(struct teacher* t) {
initPerson(&(t->super));
}
int main(){
// 结构体的声明
struct student stu;
// 函数体在使用过程中需要调用initStudent函数设置正确的指向
initStudent(&stu);
// 直接调用函数传入结构体指针
setStudentId(&stu, 2023, 607, 12);
strcpy(stu.super.name, "小明");
stu.super.setGender(&stu.super, "男");
stu.mark = 98;
// 使用printf打印输出相关数据,采用点的方式对函数进行调用
printf("学号:%d\n", stu.super.id);
printf("姓名:%s\n", stu.super.name);
// 将数字1和0转换为字符串男和女
const char* gender = stu.super.getGender(&stu.super);
printf("性别%s\n", gender);
printf("分数%d\n", stu.mark);
putchar('\n');
struct teacher t;
// 初始化teacher
initTeacher(&t);
t.super.id = 12345;
strcpy(t.super.name, "林老师");
t.super.setGender(&t.super, "男");
strcpy(t.subject, "C语言");
// 打印这些数值
printf("学号:%d\n", t.super.id);
printf("姓名:%s\n", t.super.name);
gender = t.super.getGender(&t.super);
printf("性别:%s\n", gender);
printf("科目:%s\n", t.subject);
return 0;
}
面向对象之多态
#include
#include
struct Shape {
void (*draw)(struct Shape*);
};
struct Rect {
struct Shape super;
int left;
int top;
int right;
int bottom;
};
struct Circle {
struct Shape super;
int x;
int y;
int r;
};
struct Triangle {
struct Shape super;
POINT p1;
POINT p2;
POINT p3;
};
void drawRect(struct Rect* r)
{
rectangle(r->left, r->top, r->right, r->bottom);
}
void drawCircle(struct Circle* c)
{
circle(c->x, c->y, c->r);
}
void drawTriangle(struct Triangle* t)
{
line(t->p1.x, t->p1.y, t->p2.x, t->p2.y);
line(t->p2.x, t->p2.y, t->p3.x, t->p3.y);
line(t->p3.x, t->p3.y, t->p1.x, t->p1.y);
}
void initRect(struct Rect* r)
{
r->super.draw = (void (*)(struct Shape*))drawRect;
}
void initCircle(struct Circle* c)
{
c->super.draw = (void (*)(struct Shape*))drawCircle;
}
void initTriangle(struct Triangle* t)
{
t->super.draw = (void (*)(struct Shape*))drawTriangle;
}
int main()
{
initgraph(800, 600);
setaspectratio(1, -1);
setorigin(400, 300);
setbkcolor(WHITE);
setlinecolor(BLACK);
cleardevice();
struct Rect r = { {}, -200, 200, 200, 0 };
struct Circle c = { {}, 0, 0, 100 };
struct Triangle t = { {}, {0, 200}, {-200, 0}, {200, 0} };
initRect(&r);
initCircle(&c);
initTriangle(&t);
struct Shape* arrShape[3] = {
(struct Shape*)&r, (struct Shape*)&c, (struct Shape*)&t };
for (int i = 0; i < 3; i++)
{
arrShape[i]->draw(arrShape[i]);
}
getchar();
closegraph();
return 0;
}