用c语言模拟面向对象编程

 最近有点无事可干,遇见瓶颈期了,就给自己找点事情,不浪费时间就是了。学习了gobject,就对这个用C来模拟面向对象编程的方法有点着迷。我的模拟,只能实现单继承,每一个结构体中含有了myobject中虚函数表指针。MyObject中的vtable是为了调用子类的dispose函数进行资源释放。
my_object.h

#ifndef MY_OBJECT_H_
#define MY_OBJECT_H_
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#define MY_OBJECT(obj) ((MyObject*)obj)
#define MY_OBJECT_CLASS(kclass)  ((MyObjectClass*)kclass)
#define MY_OBJECT_VTABLE(obj)  (MY_OBJECT(obj)->vtable)

#define atomic_cas(dst, old, new) __sync_bool_compare_and_swap((dst), (old), (new))
#define atomic_lock(ptr)\
while(!atomic_cas(ptr,0,1))
#define atomic_unlock(ptr)\
while(!atomic_cas(ptr,1,0))

typedef struct _MyObject MyObject;
typedef struct _MyObjectClass MyObjectClass;
struct _MyObject{
	MyObjectClass *vtable;//quite tricky
	int lock;
	int count;
};
struct _MyObjectClass{
	void (*dispose)(MyObject*obj);
};
void *my_object_create(int size);
void *my_object_ref(MyObject *obj);
void my_object_unref(MyObject *obj);
MyObjectClass *my_object_vtable();
#endif /* MY_OBJECT_H_ */

my_object.c
 my_object_free函数中调用子类的dispose函数,这个函数可以认为被子类重载。

#include "my_object.h"
void my_object_dispose(MyObject *obj);
MyObjectClass vtable={
.dispose=my_object_dispose,
};
void my_object_free(MyObject *obj){
	obj->vtable->dispose(obj);
	free(obj);
}
void *my_object_create(int size){
	MyObject *ins=NULL;
	ins=(MyObject*)malloc(size);
	memset(ins,0,size);
	if(ins){
		ins->lock=0;
		ins->count=1;
	}
	return ins;
}
void *my_object_ref(MyObject *obj){
	MyObject *ins=NULL;
	atomic_lock(&obj->lock);
	if(obj->count){
		obj->count++;
		ins=obj;
	}
	atomic_unlock(&obj->lock);
	return ins;
}
void my_object_unref(MyObject *obj){
	atomic_lock(&obj->lock);
	if(obj->count){
		obj->count--;
	}
	atomic_unlock(&obj->lock);
	if(obj->count==0){
		my_object_free(obj);
	}
}
MyObjectClass * my_object_vtable(){
	return &vtable;
}
void my_object_dispose(MyObject *obj){
printf("%s\n",__FUNCTION__);
}

 子类: my_dispatcher.h

#ifndef MY_DISPATCHER_H_
#define MY_DISPATCHER_H_
#include "my_object.h"
typedef struct _MyDispatcher MyDispatcher;
typedef struct _MyDispatcherClass MyDispatcherClass;
#define MY_DISPATCHER(obj) ((MyDispatcher*)obj)
#define MY_DISPATCHER_CLASS(kclass)((MyDispatcherClass*)kclass)
//#define my_dispatcher_call(obj,method)  (((MyDispatcherClass*)MY_OBJECT_VTABLE(obj))->method)
#define my_dispatcher_call(obj,method,...)  do{\
MyDispatcherClass *vtable=(MyDispatcherClass*)MY_OBJECT_VTABLE(obj);\
vtable->method(__VA_ARGS__);\
}while(0)
typedef int SOCKET;
struct _MyDispatcher{
	MyObject parent;
	SOCKET fd;
	void* poll_plugin;
	int request_event;
	uint8_t *buf;
	int buf_len;
};
struct _MyDispatcherClass{
	MyObjectClass parent_class;
	void (*read_event)(MyDispatcher *self);
	void (*write_event)(MyDispatcher *self);
	int (*write)(MyDispatcher *self,void *data,int len);
};
MyDispatcher* my_dispatcher_new();
void my_dispatcher_free(MyDispatcher* obj);
MyDispatcherClass* my_dispatcher_vtable();
#endif /* MY_DISPATCHER_H_ */

my_dispatcher.c

#include "my_dispatcher.h"
MyDispatcherClass  my_dispatcher_default_vtable;
static bool class_inited=false;
void my_dispatcher_class_init();
void my_dispacther_read_event(MyDispatcher *self){
	printf("%s\n",__FUNCTION__);
}
void my_dispacther_write_event(MyDispatcher *self){
	printf("%s\n",__FUNCTION__);
}
int my_dispacther_write(MyDispatcher *self,void *data,int len){
	printf("%s\n",__FUNCTION__);
	return 0;
}
MyDispatcher* my_dispatcher_new(){
	MyDispatcher *ins;
	ins=(MyDispatcher*)my_object_create(sizeof(MyDispatcher));
	MY_OBJECT_VTABLE(ins)=my_dispatcher_vtable();
	return ins;
}
void my_dispatcher_dispose(MyDispatcher* obj){
	//resource allocation, free ptr in  MyDispatcher;
	if(obj->buf){
		printf("free buffe len %d\n",obj->buf_len);
		free(obj->buf);
		obj->buf=NULL;
	}
	printf("%s\n",__FUNCTION__);
	MyObjectClass *parent_class=my_object_vtable();
	MY_OBJECT_CLASS(parent_class)->dispose(MY_OBJECT(obj));
}
void my_dispatcher_free(MyDispatcher* obj){
	my_object_unref(MY_OBJECT(obj));
}
MyDispatcherClass* my_dispatcher_vtable(){
	if(!class_inited){
		my_dispatcher_class_init();
	}
	return &my_dispatcher_default_vtable;
}
void my_dispatcher_class_init(){
	class_inited=true;
	MyDispatcherClass *kclass=&my_dispatcher_default_vtable;
	MyObjectClass *parent=my_object_vtable();
	memcpy(kclass,parent,sizeof(*parent));
	kclass->read_event=my_dispacther_read_event;
	kclass->write=my_dispacther_write;
	kclass->write_event=my_dispacther_write_event;

	MY_OBJECT_CLASS(kclass)->dispose=my_dispatcher_dispose;
}

 MY_OBJECT_CLASS(kclass)->dispose=my_dispatcher_dispose; 在创造新的类的时候,必须实现dispose函数,在这个函数中进行结构体内的指针资源的释放。不能释放结构体本身。结构体的释放有my_object_free(MY_OBJECT(obj))完成。
 孙辈:
my_dispatcher_child.h

#ifndef MY_DISPATCHER_CHILD_H_
#define MY_DISPATCHER_CHILD_H_
#include "my_dispatcher.h"
typedef struct _MyDispatcherChild MyDispatcherChild;
typedef struct _MyDispatcherChildClass MyDispatcherChildClass;
#define MY_DISPATCHER_CHILD(obj) ((MyDispatcherChild*)obj)
#define MY_DISPATCHER_CHILD_CLASS(kclass)((MyDispatcherChildClass*)kclass)
//#define my_dispatcher_child_call(obj,method)  (((MyDispatcherChildClass*)MY_OBJECT_VTABLE(obj))->method)
#define my_dispather_child_call(obj,method,...)  do{\
MyDispatcherChildClass *vtable=(MyDispatcherChildClass*)MY_OBJECT_VTABLE(obj);\
vtable->method(__VA_ARGS__);\
}while(0)
struct _MyDispatcherChild{
	MyDispatcher parent;
	int a;
};
struct _MyDispatcherChildClass{
	MyDispatcherClass parent_class;
	void (*fun1)(void);
	void (*fun2)(void);
};
MyDispatcherChild* my_dispacher_child_new();
void my_dispatcher_child_free(MyDispatcherChild* obj);
MyDispatcherChildClass* my_dispatcher_child_vtable();


#endif /* MY_DISPATCHER_CHILD_H_ */

my_dispatcher_child.c

#include "my_dispatcher_child.h"
MyDispatcherChildClass  my_dispatcherchild_default_vtable;
static bool class_inited=false;
void my_dispatcher_child_class_init(void);
void my_fun1(void){
	printf("%s\n",__FUNCTION__);
}
void my_fun2(void){
	printf("%s\n",__FUNCTION__);
}
void my_child_read_event(MyDispatcherChild *self){
	printf("%s\n",__FUNCTION__);
}
MyDispatcherChild* my_dispatcher_child_new(){
	MyDispatcherChild *ins;
	ins=(MyDispatcherChild *)my_object_create(sizeof(MyDispatcherChild));
	MY_OBJECT_VTABLE(ins)=my_dispatcher_child_vtable();
	return ins;
}
void my_dispatcher_child_dispose(MyDispatcherChild* obj){
	//resource allocation, from ptr in  MyDispatcher;
	printf("%s\n",__FUNCTION__);
	MyDispatcherClass *parent_class=my_dispatcher_vtable();
	MY_OBJECT_CLASS(parent_class)->dispose(MY_OBJECT(obj));
}
void my_dispather_child_free(MyDispatcherChild* obj){
	my_object_unref(MY_OBJECT(obj));
}
MyDispatcherChildClass* my_dispatcher_child_vtable(){
	if(!class_inited){
		my_dispatcher_child_class_init();
	}
	return &my_dispatcherchild_default_vtable;
}
void my_dispatcher_child_class_init(void){
	class_inited=true;
	MyDispatcherChildClass *kclass=&my_dispatcherchild_default_vtable;
	MyDispatcherClass *parent=my_dispatcher_vtable();
	memcpy(kclass,parent,sizeof(*parent));
	kclass->parent_class.read_event=my_child_read_event; //override
	kclass->fun1=my_fun1;
	kclass->fun2=my_fun2;

	MY_OBJECT_CLASS(kclass)->dispose=my_dispatcher_child_dispose;
}

main-test.c

#include <stdio.h>
#include <stdint.h>
#include "my_dispatcher.h"
#include "my_dispatcher_child.h"
int main(){
	MyDispatcherChild *child=my_dispatcher_child_new();
	my_dispatcher_call(child,read_event,child);
	my_dispatcher_child_call(child,fun1);
	MY_DISPATCHER(child)->buf=malloc(8*sizeof(uint8_t));
	MY_DISPATCHER(child)->buf_len=8;
	printf("%p\n",child->parent.parent.vtable);
	printf("%p\n",my_dispatcher_child_vtable());
	my_dispather_child_free(child);
    return 0;
}

 编译,使用cmake: cmake . 注意后面的点。
CMakeLists.txt

PROJECT(project)
cmake_minimum_required(VERSION 2.6)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall  -O2")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -O2")
SET(CMAKE_BUILD_TYPE "Debug")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall  -O2")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -O2")
set(CMAKE_CXX_FLAGS "-fPIC")  
set(CMAKE_C_FLAGS "-fPIC") 
add_definitions(-D__STDC_FORMAT_MACROS)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include_directories(${CMAKE_SOURCE_DIR}/)
set(object_FILES
my_object.c
my_dispatcher.c
my_dispatcher_child.c
)
add_library(object STATIC ${object_FILES})
set(EXECUTABLE_NAME "main")
add_executable(${EXECUTABLE_NAME} main-test.c)
target_link_libraries(${EXECUTABLE_NAME}  object)

  执行结果:

my_child_read_event
my_fun1
my_fun2
0x6020a0
0x6020a0
my_dispatcher_child_dispose
free buffe len 8
my_dispatcher_dispose
my_object_dispose

 Just for fun.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值