用C语言实现面向对象之封装

来源:互联网 发布:c语言break用法if 编辑:程序博客网 时间:2024/06/05 10:17

个人水平比较粗浅,想以一个初学者的角度,以C的方式去看待C++面向对象。

采用循序渐进,慢慢摸索的方式来学习,其实我也是边写边想,还会参考一些资料,有不足请指正。希望帮助自己,帮助大家更加深刻理解面向对象。

只想和大家分享,不喜勿喷,请多指教,感激不尽。

-----------------------------------正文------------------------------------

在学习面向对象时候,封装应该是我们第一个接触的特性。

说到C++中的class,很自然就想到了在C里面和他对应的关键字struct

为了使函数也能够放在struct里面,我们自然联想到了函数指针。

比如一个公司的职员类,包括姓名,工资,以及操作函数——显示职员信息。

typedef struct Employee

{

char name[20];

int salay;

void (*Print)();

}Date;

但是我们知道,class里面其实有一个隐藏指针this用来指向本类,并且每个成员函数都有一个隐藏的常量参数this

所以最终代码是这样

typedef struct Employee

{

struct Employee *This;

char name[20];

int salay;

void (*Print)(const struct Employee);

}Employee;

void Print(const struct Employee *This)

{

printf("My Name is %s\n",This->name);

}

对了,我们需要一个构造函数,来对结构体中的函数指针初始化。

要怎么写呢?。。。。

先想想我们在main函数里面这么调用的吧,在C++里面我们希望是

int main()

{

Employee a;

a.Print();

return 0;

}

为了尽量仿照,我觉得应该是这样的调用:

int main()

{

Employee a=EmployeeInit();

a.Print(&a);

return 0;

}

这下知道该怎么写了吧。

Employee EmployeeInit()

{

Employee *p = (Employee *)malloc(sizeof(Employee));

strcpy(p->name,"Li Hua");

p->salay = 1000;

p->This =p;        //初始化This指针

p->Print = Print;  //这里初始化函数指针

return *p;

}

这其实就是类中的构造函数的实现。有了构造函数,当然得有析构函数,要不然得内存泄露了。在C++中自动调用这些,而现在我们得手动调用了。

最后代码是这样的:

typedef struct Employee

{

struct Employee *This;

char name[20];

int salay;

void (*Print)(const struct Employee*);

}Employee;

void Print(const struct Employee *This)

{

printf("My Name is %s\n",This->name);

printf("My Salay are %d\n",This->salay);

}

Employee EmployeeInit()

{

Employee *p = (Employee *)malloc(sizeof(Employee));

strcpy(p->name,"Li Hua");

p->salay = 1000;

p->This =p;        //初始化This指针

p->Print = Print;  //这里初始化函数指针

return *p;

}

bool EmployeeDestructor(Employee x)

{

free(x.This);

return true;

}

int main()

{

Employee a=EmployeeInit();

a.Print(a.This);

EmployeeDestructor(a);

return 0;

}

运行结果

 

但是这里遇到一个问题,我们虽然通过这种办法把数据和操作放在一块儿了,但是没有体现到数据保护,我们仍然能够访问到私有成员namesalay,这不符合封装的思想。

 

(我们并不想外界访问到name,salay这些数据

 

所以我们要想办法实现C++里面的访问控制符,private,public

想了挺久,决定用2个类共同来实现,一个类用来存放私有的,另一个类来放public接口,对外只公开public

对了,顺便改一下构造函数。C里面木有函数重载,只能有一个构造函数是硬伤啊。

最终代码变成这样了:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

//这个结构体是私有的,相当于private成员,不允许创建对象

typedef struct Employee_P

{

char name[20];

int salay;

}Employee_P;

 

//相当于public的成员

typedef struct Employee

struct Employee_P *This;     //This指针也得放到类里面

void (*Print)(const struct Employee*); //包含函数指针,用来访问这个函数

}Employee;

 

void Print(const struct Employee *This)

{

Employee_P *it = This->This; 

printf("My Name is %s\n",it->name);

printf("My Salay are %d\n",it->salay);

}

 

/*构造函数*/

Employee EmployeeInit(char *name,int salay)

{

Employee ret;

Employee_P *p =(Employee_P *)malloc(sizeof(Employee_P));


strcpy(p->name,name);

p->salay = salay;


ret.This =p;        //初始化This指针

ret.Print =Print; //这里初始化函数指针,让它指向Print这个函数

return ret;

}

 

/*析构函数*/

bool EmployeeDestructor(Employee x)

{

free(x.This);

return true;

}

 

int main()

{

Employee a=EmployeeInit("Li Hua",1000);

Employee b=EmployeeInit("Xiao Meng",10000);

a.Print(&a);

b.Print(&b);

EmployeeDestructor(a);

EmployeeDestructor(b);

return 0;

}

 

现在,我们只能访问到a的对外接口了。


这样我们的a对象就不能访问到namesalay了。

如果别人无聊一定要创建一个Employee_P 类来访问你的成员。

你还可以分成多个文件,然后只把Employee 的声明放在文件里面,对外公开Employee.h 的头文件,这样别人就找不到你的Employee_P声明和定义,想创建也创建不了了(我没试过,猜测的,不负责任)。


最终,虽然有点别扭,但是面向对象的一大特性,封装,就这么被我们实现了。(貌似是最简单的)

0 0
原创粉丝点击