linuxc成长之路-c语言面向对象编程

由于长期跟面向对象开发语言打交道,作为一个c语言入门者(差不多零基础哭),接触C语言最大疼点就是不习惯面向过程的开发。为了快速上手c语言,还是使用自己习惯编程思维去开发。这次主要针对面向对象封装、继承、多态3大特点进行实现。以下记录一下花了一整晚写的c语言面向对象的代码。


一、首先创建头文件object.h,该头文件是主要作用是定义面向对象一些关键字,代码如下

#include <stdlib.h>
#include <string.h>
#include "base.h"
#ifndef OBJECT_H
#define OBJECT_H


//
#define PUBLIC ;
#define PRIVATE(PrivateName) struct PrivateName
#define CLASS(ClassName) struct ClassName
#define THIS(ClassName) CLASS(ClassName)*this
#define PLACEHOLDER(ClassName) char placeholder[sizeof(CLASS(ClassName))-sizeof(char*)] //substract first pointer size
//memory define
#define NEW(type) ((type*)malloc(sizeof(type)))
#define DELETE(memory) free(memory)


static void setValue(void* property, void* value,U32 len)
{
    memcpy(property, value,len);
}
static void getValue(void* property, void* value,U32 len)
{
    memcpy(value, property,len);
}
#endif


上述代码中PUBLIC、PRIVATE、CLASS、THIS、NEW、DELETE为面向对象语言最常见的关键字,定义的目的为了简化书写及方便理解,并实现本次面向对象的功能。以下介绍一下各个关键字作用:

PUBLIC:定义公共的变量及函数,使外部能进行访问

PRIVATE:通过在private.h头文件中定义不开放变量及函数,达到对象封装的效果

CLASS:定义一个结构体,用作类信息定义

THIS:将CLASS的第一个成员this指向自己,目的为了在继承的时候,通过this找到基类的成员。

NEW:为类分配空间,实例化对象

DELETE:删除分配的空间,跟NEW成对出现

setValue,getValue为数据的get、set函数,用于对象数据获取与设置

注:PLACEHOLDER是后来加上去的,博主在使用过程中发现子类不能定义变量和函数指针,原因是子类的私有变量使用了THIS后面的地址空间,结果直接覆盖了父类的内存,所以增加PLACEHOLDER做占位用,使子类定义的变量和函数指针能指向正确的地址

二、创建基类person.h,根据面向对象类定义的实现封装效果

#include <stdlib.h>
#include <string.h>
#include "../../../base/include/object.h"
#include "person.h"
#ifndef MAN_H
#define MAN_H


CLASS(Man);


PUBLIC void Man_constructor(CLASS(Man)*);
PUBLIC void setname_man(CLASS(Person)* self,char* str);
PUBLIC void getname_man(CLASS(Person)* self,char* str);


CLASS(Man){
    THIS(Person);
    PLACEHOLDER(Person);//fix memory overwrite bug
};


void testMan();
#endif

这里代码有点多,我简单说明一下思法:

person_private.h主要是私有类型,里面定义的内容不开放给外部,内容主要如下:

#include <string.h>
#include "../../../base/include/object.h"


#ifndef PERSON_PRIVATE_H
#define PERSON_PRIVATE_H


PRIVATE(Person_Private);
PRIVATE(Person_Private)
{
    int age;
    char name[255];
};


#endif

CLASS(Person),这里定义一个类信息,其中THIS为当前类实例的指针

Person_constructor为构造函数,主要初始化CLASS(Person)对象信息,如绑定setage、getage、setname、getname各种函数

三、用上面person封装思想来创建子类man.h,并实现面向对象继承及多态的特性

#include <stdlib.h>
#include <string.h>
#include "../../../base/include/object.h"
#include "person.h"
#ifndef MAN_H
#define MAN_H

CLASS(Man);

PUBLIC void Man_constructor(CLASS(Man)*);
PUBLIC void setname_man(CLASS(Person)* self,char* str);
PUBLIC void getname_man(CLASS(Person)* self,char* str);

CLASS(Man){
    THIS(Person);
};


PUBLIC void Man_constructor(CLASS(Man)*self)
{
    self->this=(CLASS(Person)*)self;
    Person_constructor(self->this);
    self->this->getName=getname_man;
    self->this->setName=setname_man;
}

PUBLIC void setname_man(CLASS(Person)* self,char* str)
{
    str = strcat(str, " man set");
    setValue(self->private.name,str, strlen(str)+1);
}
PUBLIC void getname_man(CLASS(Person)* self,char* str)
{
    getValue(self->private.name, str, strlen(self->private.name)+1);
    strcat(str, " man get");
}

void testMan();
#endif
由上面代码可以看出,子类的代码比父类少了很多,这就是面向对象的好处了 大笑。这里也是简单地说明一下:

THIS(Person)作用是将子类地址入口指向CLASS(Man)的第一个成员,用这个做法可以通过CLASS(Person)*强制转换CLASS(Man)对象。

Person_constructor(self->this)作用是子类被实例化构造时,对基类也进行实例化。这里就是继承了,是不是很简单呢。

self->this->getName=getname_man和self->this->setName=setname_man就是面向对象多态的实现,其实就是覆盖父类的方法(高级语言叫重写)

四、实现man.c和oo.c,看看面向对象实现的效果吧

man.c代码如下

#include <stdio.h>
#include "../include/man.h"
void testMan()
{
    CLASS(Man)* man = NEW(CLASS(Man));//new
    Man_constructor(man);//构造函数    
    CLASS(Person)* person=(CLASS(Person)*)man;
    char str[255]="person";
    person->setName(person,(char*)str);
    char name[255];
    person->getName(person,name);
    person->setAge(person,20);
    int age = person->getAge(person);
    DELETE(man);
    printf("%s",name);
    printf("%d",age);
    fflush(stdout); 
}
oo.c代码如下

#include <stdio.h>

int main(int argc,char* argv[])
{
    testMan();
    return 0;
}
下面是调用执行的结果,可以看出这里成功打印子类的信息及继承父类的信息,证明这次面向对象实现是成功的


另外需要补充说明一下,为了方便文中类定义都是头文件中完成,实际项目应放在具体的c文件里面,原因是避免编译时出现重复定义的问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值