C 语言部分实现面向对象的继承特性

来源:互联网 发布:淘宝福利秀 编辑:程序博客网 时间:2024/05/16 14:31
最近在研究Linux源码的时候遇到很多不曾见过的C语言用法,尤其是一些面相对象的特性。最熟悉的是C99标准,最新的C11标准没有仔细研究过,泛泛看了一下资料觉得也主要是增加了一些对多线程支持的特性,对于面向对象的特性应该没有。

搜索了一下,找到一篇很好的文章。该文章采用C语言很灵巧的实现了部分面向对象的继承特性
遗憾的是源代码貌似有问题,对于struct的内存布局有问题,同时也编译不过,因此我修改了一下,随后也会和原文作者一起讨论和分析。

感兴趣的同学,请先移步到本文的参考文章看下:
http://www.cnblogs.com/haippy/archive/2012/12/31/2840501.html

因为我对代码进行了不少改动,包括基类的设计实现、封装性方面,因此文章属性定为原创,这里先向原作者表示歉意和感谢。

下面是我修改的代码,在VS2008和gcc中编译过的,可以正常运行。VS2008中仅支持C89的编译标准,因此如果写C代码最好是用gcc编译。


//animal_base.h:
#ifndef _ANIMAL_H_
#define _ANIMAL_H_

typedef struct animal_s_ animal_t;
typedef struct animal_ops_s_ animal_ops_t;

/* 动物的基本行为 */
struct animal_ops_s_ {
    void (*eat)(char *food);
    void (*walk)(int steps);
    void (*talk)(char *msg);
};

/* 动物类,是所有动物类的基类,也是抽象类 */
struct animal_s_ {
    animal_ops_t animal_ops; /* 动物的基本行为 */
};

/* 基类的构造函数,需要显示调用 */
animal_t * animal_init();

/* 基类的有关操作,如吃,走,说等等 */
void animal_eat(animal_t *animal, char *food);
void animal_walk(animal_t *animal, int steps);
void animal_talk(animal_t *animal, char *msg);

/* 基类的析构函数,需要显示调用 */
void animal_die(animal_t *animal);

#endif /* _ANIMAL_H_ */

//animal_base.c
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "animal_base.h"

/* 基类的构造函数,需要显示调用 */
animal_t * animal_init()
{
    animal_t *animal = (animal_t *)malloc(sizeof(animal_ops_t));
    memset(animal, 0, sizeof(animal_ops_t));
    return animal;
}

/* 基类的有关操作,如吃,走,说等等 */
void animal_eat(animal_t *animal, char *food)
{
    animal->animal_ops.eat(food);
}

void animal_walk(animal_t *animal, int steps)
{
    animal->animal_ops.walk(steps);
}

void animal_talk(animal_t *animal, char *msg)
{
    animal->animal_ops.talk(msg);
}

/* 基类的析构函数,需要显示调用 */
void animal_die(animal_t *animal)
{
    assert(animal != NULL);
    free(animal);
}

//cat.h
#include "animal_base.h"

typedef struct cat_s_ cat_t;

struct cat_s_ {
    animal_t base; /*animal基类数据成员必须位于第一个成员声明的位置 */

    /* 以下还可以添加与 cat 相关的属性和方法(函数指针), 如: */
    /* char *owner; // cat 的主人 */
    /* void (*hunt)(const char *rabbit); // 猎兔犬 */
};

cat_t * cat_init();
void cat_die(cat_t * cat);


//cat.c
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cat.h"

static void eat(char *food);
static void walk(int steps);
static void talk(char *msg);

cat_t * cat_init()
{
    cat_t *cat = (cat_t *)malloc(sizeof(cat_t));
    animal_t *animal = (animal_t *)animal_init();
    memcpy(&(cat->base), animal, sizeof(animal_t));
    cat->base.animal_ops.eat = eat;
    cat->base.animal_ops.walk = walk;
    cat->base.animal_ops.talk = talk;
    animal_die(animal);
    return cat;
}

void cat_die(cat_t *cat)
{
    assert(cat != NULL);
    free(cat);
}

static void eat(char *food)
{
    printf("I'm a cat, I eat %s\n", food);
}

static void walk(int steps)
{
    printf("I'm a cat, I can jump %d steps one time\n", steps);
}

static void talk(char *msg)
{
    printf("I'm a cat, I talk my language %s\n", msg);
}


//dog.h
#include "animal_base.h"

typedef struct dog_s_ dog_t;

struct dog_s_ {
    animal_t base; /* animal基类数据成员必须位于第一个成员声明的位置*/

    /* 以下还可以添加与 dog 相关的属性和方法(函数指针), 如: */
    /* char *owner; // dog 的主人 */
    /* void (*hunt)(const char *rabbit); // 猎兔犬 */
};

dog_t * dog_init();
void dog_die(dog_t * dog);
 

//dog.c
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dog.h"

static void eat(char *food);
static void walk(int steps);
static void talk(char *msg);

dog_t * dog_init()
{
    dog_t *dog = (dog_t *)malloc(sizeof(dog_t));
    animal_t *animal = (animal_t *)animal_init();
    memcpy(dog, animal, sizeof(animal_t));
    dog->base.animal_ops.eat = eat;
    dog->base.animal_ops.walk = walk;
    dog->base.animal_ops.talk = talk;
    animal_die(animal);
    return dog;
}

void dog_die(dog_t *dog)
{
    assert(dog != NULL);
    free(dog);
}

static void eat(char *food)
{
    printf("I'm a dog, I eat %s\n", food);
}

static void walk(int steps)
{
    printf("I'm a dog, I can jump %d steps one time\n", steps);
}

static void talk(char *msg)
{
    printf("I'm a dog, I talk my language %s\n", msg);
}
 


//main.c
#include <stdio.h>
#include "animal_base.h"
#include "dog.h"
#include "cat.h"

int main(int argc, const char *argv[])
{
    dog_t *dog = dog_init();
    cat_t *cat = cat_init();

    /* dog 类测试 */
    animal_eat((animal_t *)dog, "bones");
    animal_walk((animal_t *)dog, 5);
    animal_talk((animal_t *)dog, "wuang wuang wuang...");
    /* cat 类测试 */
    animal_eat((animal_t *)cat, "fish");
    animal_walk((animal_t *)cat, 3);
    animal_talk((animal_t *)cat, "miao miao miao...");

    dog_die(dog);
    cat_die(cat);

    getchar();
}

运行结果:



(完)

题后: 本文中实际上是有商榷的地方的,请移步重构后的版本

0 0