C语言面对对象设计模式汇编

抽象数据类型

抽象数据类型:方法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;
}

时间: 2024-10-13 11:39:46

C语言面对对象设计模式汇编的相关文章

Android 内功心法(番外)——写在设计模式前,面对对象编程基础

我写的一系列"Android 内功心法"着重讲到android中经常使用的设计模式.那么如果有些程序员刚刚接触设计模式,那就有必要确定一下自己面对对象编程的基础是否牢固了. 因为这直接关系到你阅读设计模式的速度和理解质量. 接下来我将简单介绍java中面对对象编程的一些基础知识. 1,类和修饰符 public class ClassTest{ public ClassTest{ } public void test(){ } } 其中类的定义是以"class"来决定

《设计模式之禅》笔记整理--面对对象设计六大原则

第一章.面对对象设计六大原则: (1).单一职责原则:应该有且只有一个原因引起类的变更. 为什么要用单一职责原则:(1).类的复杂性降低,实现什么职责都有清晰明确的定义. (2).可读性提高,复杂性降低,当然可读性提高了. (3).可维护性提高,可读性提高,当然更容易维护了. (4).变更引起的风险降低,一个接口修改,只对相应的实现类有影响. 职责划分的例子:电话过程可以划分为两个职责:(1).协议管理(2).数据传送 :RBAC模型,基于角色的访问控制 (2).里氏替换原则:目的:增强程序的健

面对对象_面向对象的概念、类与对象的关系

面向对象的基本概念: 1.什么是面向对象 1.面向对象是一种编程思想 2.面向对象是一种思考问题的思维方式 2.建立面向对象的思维方式 1.先整体,再局部 2.先抽象,在具体 3.能做什么,再怎么做 3.如何学习面向对象 1.掌握一门面向对象语言的语法 2.熟悉面向对象的设计原则 3.熟悉面向对象的设计模式 面对对象的概述:   1.面对对象的三个特征(公认的):封装,继承,多态.(也可以说是四大特征:封装,继承,多态,抽象)   2.开发中先找对象,没有就建立一个对象,实际就是找对象,建立对象

js面对对象编程

说到js,很大一部分人会说我很熟悉,在日常的web开发中经常用,那么你的js代码是符合面对对象思路的吗?那你会问我面向过程的js代码有什么不好吗?我的感受是面对对象的js编码更加简洁,减少了混乱,可维护行增强,适合编写富客户端时应用. 好了,首先看看js里如何定义对象: <html> <head> <script type="text/javascript"> var obj=new Object(); obj.name='josh'; obj.ag

面对对象基础

1.面对对象不是所有情形都适用 1.1函数式编程 def fun1(arg1): pass def fun2(arg1,arg2): pass fun1("acker") fun2("...") 2.1面对对象编程 class humanBeing: def fun1(self, arg1): pass def fun2(self,arg1, arg2): pass obj1 = humanBeing() obj1.fun1('wuwen') obj2.fun2('

初遇面对对象

问题一:为什么要出现面对对象的语言,用来解决什么样的问题? 所有的程序设计语言都提供抽象,汇编语言是对底层机器的抽象,但仍要求程序员按计算机的结构去思考,而程序员要做的必须要能在机器模型和实际上要解决的问题的模型建立联系.(实际上是一个建模的过程)早期是对要解决的问题进行建模,这就是面对过程的,但是缺陷很快就被发现,它所编写的程序难以维护或者说维护费用昂贵.面对对象的方法为程序员提供了在问题空间中表示各种事物元素的工具.好处是:当我们描述解决方案的代码的时候,也就是在表达该问题的文字.使得程序员

javascript面对对象编程 之继承

上一篇博客中为大家介绍了javascript面向对象编程原则的封装,今天为大家介绍继承,在javascript中没有类的概念,所有不能像c#,java语言那样,直接的用类去继承类.比如现在有比如,现在有一个"动物"对象的构造函数. function Animal(){ this.species = "动物"; } 还有一个"猫"对象的构造函数. function Cat(name,color){ this.name = name; this.co

Javascript面对对象. 第一篇

Javascript,有两个种开发模式: 1.函数式(过程化)2.面对对象(oop),面对对象语言有一个标志,就是类,而通过类可以创建任何多个属性和方法,而Ecmascript没有类的概念,因此它的对象也与基于类的语言中的对象有所不同. 1.创建对象 创建一个对象,然后给这个对象新建属性和方法. var box=new Object();//创建对象 box.name='link'; //添加属性,值 box.age=45; box.run=function(){//创建方法 return th

35.python全栈之路:面对对象进阶

面对对象进阶 1.多继承中的self class A: def bar(self): print('BAR') self.f1() ''' self本身代表的D类的对象d1 d1如果要在他的父类中去寻找f1 首先应该去C类 ''' class B(A): def f1(self): print('B') class C: def f1(self): print('C') class D(C, B): pass d1 = D() d1.bar() 流程分析: d1 = D(),最终找到了objec