面向对象编程——C语言

面向对象编程——C语言

Posted by naiquan.hu on September 17, 2018

1. 抽象数据类型

集合中可以存放任意数据类型,提供一些方法来操作它。因此它里面存放的应该是抽象数据类型。

set.h

#ifndef SET_H
#define SET_H
extern const void * Set;
void * add (void * set, const void * element);
void * find (const void * set, const void * element);
void * drop (void * set, const void * element);
int contains (const void * set, const void * element);
#endif
object.h

#ifndef OBJECT_H
#define OBJECT_H
extern const void * Object; /* new(Object); */
int differ (const void * a, const void * b);
#endif
new.h

#ifndef NEW_H
#define NEW_H
void * new (const void * type, ...);
void delete (void * item);
#endif

上面是提供给外界的可见接口,无需改变,当不同的实现只需改变下面的实现部分即可。

impl.h

#ifndef IMPL_H
#define IMPL_H
struct Set
{
    unsigned count; //count reconrds the number of elements in a set
};
struct Object
{
    unsigned count; //count records how many times this element has been added to the set
    struct Set * in;
};
#endif

方法的具体实现

impl.c

#include <assert.h>
#include <stdlib.h>
#include "new.h"
#include "set.h"
#include "object.h"
#include "impl.h"

void * new (const void * type, ...)
{
    const size_t size = * (const size_t *) type;
    void * p = calloc(1, size);
    assert(p);
    return p;
}
void delete (void * _item)
{
    struct Object * item = _item;
    if (item)
    {
        free(item);
    }
}

void * add (void * _set, void * _element)
{
    struct Set * set = _set;
    struct Object * element = (void *) _element;
    assert(set);
    assert(element);

    if (! element->in)
        element->in = set;
    else
        assert(element->in == set);
    ++element->count, ++set->count;
    return (void *) element;
}

void * find (const void * _set, const void * _element)
{
    const struct Set * set = _set;
    const struct Object * element = _element;
    assert(set);
    assert(element);
    return element->in == set ? (void *) element : 0;
}

int contains (const void * _set, const void * _element)
{
    return find(_set, _element) != 0;
}

void * drop (void * _set, const void * _element)
{
    struct Set * set = _set;
    struct Object * element = find(_set, _element);
    if (element)
    {
        if(--element->count == 0)
            element->in = 0;
        --set->count;
    }
    return element;
}
unsigned count (const void * _set)
{
    const struct Set * set = _set;
    assert(set);
    return set->count;
}
int differ (const void * a, const void * b)
{
    return a != b;
}
main.c

#include <stdio.h>
#include "new.h"
#include "object.h"
#include "set.h"
#include "impl.h"


static size_t _Set = sizeof(struct Set);
static size_t _Object = sizeof(struct Object);
static void * pSet = & _Set;
static void * pObject = & _Object;
int main ()
{
    void * s = new(pSet);
    void * a = add(s, new(pObject));
    void * b = add(s, new(pObject));
    void * c = new(pObject);
    if (contains(s, a) && contains(s, b))
        puts("ok");
    if (contains(s, c))
        puts("contains?");
    if (differ(a, add(s, a)))
        puts("differ?");
    if (contains(s, drop(s, a)))
        puts("drop?");
    delete(drop(s, b));
    delete(drop(s, c));
    return 0;
}

2. 类的实现

类的创建,销毁,克隆

class.h

#ifndef CLASS_H
#define CLASS_H
#include <stddef.h>
typedef 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);
}Class;
#endif
string.h

#ifndef STRING_H
#define STRING_H
#include "class.h"
typedef struct _String {
    const void * Class; /* must be first */
    char * text;
}String;
extern const void * pString;
void * String_ctor (void * _self, va_list * app);
void * String_dtor (void * _self);
void * String_clone (const void * _self);
int String_differ (const void * _self, const void * _b);
#endif

string的实现

string.c

#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "string.h"
#include "new.h"

void * String_ctor (void * _self, va_list * app)
{
    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;
}
void * String_dtor (void * _self)
{
    String * self = _self;
    free(self->text), self->text = 0;
    return self;
}
void * String_clone (const void * _self)
{
    const String * self = _self;
    return new(pString, self->text);
}
int String_differ (const void * _self, const void * _b)
{
    const String * self = _self;
    const String * b = _b;
    if (self == b)
        return 0;
    if (! b || b->Class != pString)
        return 1;
    return strcmp(self->text, b->text);
}
new.h

#ifndef NEW_H
#define NEW_H
void * new (const void * type, ...);
void delete (void * self);
void * clone (const void * self);
int differ (const void * self, const void * b);
size_t sizeOf (const void * self);
#endif

new的实现

new.c

#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#include "class.h"
#include "new.h"

void * new (const void * _class, ...)
{
    const Class *class = _class;
    void *p = calloc(1, class->size);
    assert(p);
    *(const Class **) p = class;
    if(class->ctor)
    {
        va_list ap;
        va_start(ap, _class);
        p = class->ctor(p, &ap);
        va_end(ap);
    }
    return p;
}
void delete (void * self)
{
    const Class ** cp = self;
    if (self && *cp && (*cp)->dtor)
        self = (*cp)->dtor(self);
    free(self);
}
int differ (const void * self, const void * b)
{
    const Class * const * cp = self;
    assert(self && *cp && (*cp)->differ);
    return (*cp)->differ(self, b);
}
void * clone (const void * self)
{
    const Class * const * cp = self;
    assert(self && *cp && (*cp)->clone);
    return (*cp)->clone(self);
}
size_t sizeOf (const void * self)
{
    const Class * const * cp = self;
    assert(self && * cp);
    return (*cp)->size;
}
main.c

#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include "string.h"
#include "new.h"

static const Class _String = {
    sizeof(String),
    String_ctor, String_dtor,
    String_clone, String_differ
};
const void * pString = &_String;
int main ()
{
    void * a = new(pString, "a"), *aa = clone(a);
    void * b = new(pString, "b");
    if (differ(a, b))
        puts("ok");
    if (differ(a, aa))
        puts("differ?");
    if (a == aa)
        puts("clone?");
    delete(a), delete(aa), delete(b);
    return 0;
}