抽象数据类型
抽象数据类型:方法A
要点:
a. 头文件只提供类型声明和接口声明
b. 类型定义和接口实现在.c中完成
c. 接口支持参数类型检查
/* stach.h */ #ifndef STACK_H #define STACK_H typedef struct stack *stack; extern stack stack_new(void); extern void stack_free(stack *stk); extern int stack_empty(stack stk); extern void stack_push(stack stk, void *x); extern void *stack_pop(stack stk);
抽象数据类型:方法B
要点:
a. 头文件只提供接口声明
b. 定义一个 void * 指针类型全局变量,封装接口需要的所有和对象相关的信息
c. 类型定义和接口实现在.c中完成
d. 接口不支持参数类型检查
/* set.h */ #ifndef SET_H #define SET_H extern const void * Set; extern void * set_new (const void * type, ...); extern void set_delete (void * item); extern void * set_add (void * set, const void * element); extern void * set_find (const void * set, const void * element); extern void * set_drop (void * set, const void * element); extern int set_contains (const void * set, const void * element); extern unsigned set_count (const void * set); #endif
对象继承
对象继承:方法A
要点:
a. 纯虚基类以聚合(关联)方式继承,类型为const void *以便于信息隐藏
b. 非纯虚基类以组合方式继承,类型为const struct superclass_name
c. 所有基类必须作为派生类第一个成员
d. 基类在派生类中以命名为‘_‘进行信息隐藏
e. 纯虚基类在各个派生类中实例化
f. 对外部不暴露具体数据类型
extern const void * Circle; /* new(Circle, x, y, rad) */ extern const void * Point; /* new(Point, x, y); */ void * new (const void * class, ...); void delete (void * item); void draw (const void * self); void move (void * point, int dx, int dy); /* .c */ struct Class { size_t size; void * (* ctor) (void * self, va_list * app); void * (* dtor) (void * self); void (* draw) (const void * self); }; struct Point { const void * class; int x, y; }; struct Circle { const struct Point _; int rad; }; void move (void * _self, int dx, int dy) { struct Point * self = _self; self -> x += dx, self -> y += dy; } void draw (const void * self) { const struct Class * const * cp = self; assert(self && * cp && (* cp) -> draw); (* cp) -> draw(self); }
对象继承:方法B
要点:
a. 基类作为派生类的一个字段,但不必作为派生类的第一个字段
b. 通过 container_of 方法找到派生类的基类
c. 对外不暴露派生类类型,但暴露基类类型
d. 支持多重继承
e. 多用于业务逻辑/流程在派生类模块中实现的场景,基类为派生类提供公共服务
struct ep_device { struct usb_endpoint_descriptor *desc; struct usb_device *udev; struct device dev; }; #define to_ep_device(_dev) \ container_of(_dev, struct ep_device, dev)
对象继承:方法C
要点:
a. 派生类作为基类的一个字段,此字段以void *类型定义
b. 在派生类模块中对基类此字段进行初始化
c. 对外不暴露派生类类型,但暴露基类类型
d. 多用于业务逻辑/流程在基类模块中实现的场景,派生类为基类提供个性化服务
struct super_block { /* omitted */ void *s_fs_info; /* Filesystem private info */ /* omitted */ }; int autofs_fill_super(struct super_block *s, void *data, int silent) { struct autofs_sb_info *sbi; /* omitted */ sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) goto fail_unlock; s->s_fs_info = sbi; /* omitted */ }
接口继承
接口继承
要点:
a. 派生类通过字段inherits继承基类
b. 派生类通过ata_finalize_port_ops初始化
c. C99中,若数据结构体中的某个字段被重复初始化,最后一次初始化有效。根据这个特点,实现对象的覆盖功能。
struct ata_port_operations { /* omitted */ void (*sff_dev_select)(struct ata_port *ap, unsigned int device); /* omitted */ /* * ->inherits must be the last field and all the preceding * fields must be pointers. */ const struct ata_port_operations *inherits; }; const struct ata_port_operations ata_base_port_ops = { .prereset = ata_std_prereset, .postreset = ata_std_postreset, .error_handler = ata_std_error_handler, }; const struct ata_port_operations sata_port_ops = { .inherits = &ata_base_port_ops, .qc_defer = ata_std_qc_defer, .hardreset = sata_std_hardreset, }; const struct ata_port_operations sata_pmp_port_ops = { .inherits = &sata_port_ops, .pmp_prereset = ata_std_prereset, .pmp_hardreset = sata_std_hardreset, .pmp_postreset = ata_std_postreset, .error_handler = sata_pmp_error_handler, }; static void ata_finalize_port_ops(struct ata_port_operations *ops) { static DEFINE_SPINLOCK(lock); const struct ata_port_operations *cur; void **begin = (void **)ops; void **end = (void **)&ops->inherits; void **pp; if (!ops || !ops->inherits) return; spin_lock(&lock); for (cur = ops->inherits; cur; cur = cur->inherits) { void **inherit = (void **)cur; for (pp = begin; pp < end; pp++, inherit++) if (!*pp) *pp = *inherit; } for (pp = begin; pp < end; pp++) if (IS_ERR(*pp)) *pp = NULL; ops->inherits = NULL; spin_unlock(&lock); }
函数模板
函数模板: 参数多态
要点:
a. 通用操作,如:构造函数、解析函数、比较函数、复制函数等
b. 函数模板参数以 void * 定义
c. 把相关模板函数转化为纯虚基类的成员函数
d. 模板函数基于纯虚基类上实现
e. 每个派生类继承纯虚基类,纯虚基类以关联方式继承,类型为const void *以便于信息隐藏
f. 所有基类必须作为派生类第一个成员,所以不支持多重继承方式
g. 派生类具体实现自己特定接口
/* new.h */ void * new (const void * class, ...); void delete (void * item); void * clone (const void * self); int differ (const void * self, const void * b); size_t sizeOf (const void * self); /* new.r */ struct Class { size_t size; void * (* ctor) (void * self, va_list * app); void * (* dtor) (void * self); void * (* clone) (const void * self); int (* differ) (const void * self, const void * b); }; /* new.c */ void * new (const void * _class, ...) { const struct Class * class = _class; void * p = calloc(1, class -> size); assert(p); * (const struct Class **) p = class; if (class -> ctor) { va_list ap; va_start(ap, _class); p = class -> ctor(p, & ap); va_end(ap); } return p; } /* string.h */ extern const void * String; /* string.c */ struct String { const void * class; /* must be first */ char * text; }; static void * String_ctor (void * _self, va_list * app) { struct String * self = _self; const char * text = va_arg(* app, const char *); self -> text = malloc(strlen(text) + 1); assert(self -> text); strcpy(self -> text, text); return self; } static const struct Class _String = { sizeof(struct String), String_ctor, String_dtor, String_clone, String_differ }; const void * String = & _String; /* app.c */ int main () { void * a = new(String, "a"); //... delete(a); return 0; }