c語言中繼承和多態的簡單實現

  C語言自己是不支持繼承和多態的,但其實在 C 的世界裏,有一套很是有名的面向對象的框架,用的也很是廣,那就是 GObject,它是整個圖形界面開發庫 GTK 的基石,在IBM developerWorks上有一篇很好的文章介紹 GObject《GObject對象系統》。另外,在 Linux 內核裏面也大量使用了面向對象的思想,好比虛擬文件系統,設備驅動等模塊,在 lwn 上有兩篇文章就講到了內核中的面向對象,詳細請看:《Object oriented design patterns in the kernel, part 1》,《Object oriented design patterns in the kernel, part 2》。html

  c語言裏繼承和多態的實現主要經過函數指針來實現,如今咱們就來動手實現C語言的繼承與多態,咱們以比較經典的動物世界中的實例來舉例:假設動物們(包括人)都會吃(Eat),會走(Walk),會說(Talk),而派生類爲 dog(汪星人) 和 cat(喵星人),固然還能夠是更多,dog 和 cat 都有本身獨特的 eat, walk 和 talk 方式,那麼大體的代碼以下:linux

基類代碼 animal-base.h|c:框架

/*
 * =============================================================================
 *
 *       Filename:  animal-base.h
 *
 *    Description:  animal base class.
 *      
 *
 * =============================================================================
 */
#ifndef _ANIMAL_H_
#define _ANIMAL_H_

typedef struct animal_s_ animal_t;
typedef struct animal_ops_s_ animal_ops_t;


/* 動物類,是全部動物類的基類,也是抽象類 */
struct animal_s_ {
    char *name; /*< 動物的名稱 */
    animal_ops_t *animal_ops; /* 動物的基本行爲 */
};

/* 動物的基本行爲 */
struct animal_ops_s_ {
    /* 動物吃了什麼食物 */
    void (*eat)(char *food);
    /* 動物走了多少步 */
    void (*walk)(int steps);
    /* 動物在說什麼 */
    void (*talk)(char *msg);
};

/* 基類的構造函數,須要顯示調用 */
extern animal_t * animal_init(char *name);

/* 基類的有關操做,如吃,走,說等等 */
extern void animal_eat(animal_t *animal, char *food);
extern void animal_walk(animal_t *animal, int steps);
extern void animal_talk(animal_t *animal, char *msg);

/* 基類的析構函數,須要顯示調用 */
extern void animal_die(animal_t *animal);

#endif  /* _ANIMAL_H_ */
複製代碼
複製代碼
/*
 * =============================================================================
 *
 *       Filename:  animal-base.c
 *
 *    Description:  animal base class.
 *
 * =============================================================================
 */
#include <assert.h>
#include <stdlib.h>
#include <string.h>

#include "animal-base.h"

/* 基類的構造函數,須要顯示調用 */
animal_t * animal_init(char *name)
{
    assert(name != NULL);
    size_t name_len = strlen(name);

    animal_t *animal = (animal_t *)malloc(sizeof(animal_t)
            + sizeof(animal_ops_t) + name_len + 1);
    memset(animal, 0, (sizeof(animal_t) + sizeof(animal_ops_t)
                + name_len + 1));
    animal->name = (char *)animal + sizeof(animal_t);
    memcpy(animal, name, name_len);
    animal->animal_ops = (animal_ops_t *)((char *)animal
            + sizeof(animal_t) + name_len + 1);

    return animal;
}

/* 基類的有關操做,如吃,走,說等等 */
void animal_eat(animal_t *animal, char *food)
{
    animal->animal_ops->eat(food);
    return;
}

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

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

/* 基類的析構函數,須要顯示調用 */
void animal_die(animal_t *animal)
{
    assert(animal != NULL);

    free(animal);
    return;
}
複製代碼

汪星人 dog 類的實現代碼:函數

複製代碼
#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); // 獵兔犬 */
};

extern dog_t * dog_init();
extern void dog_die(dog_t * dog);
複製代碼
複製代碼
/*
 * =============================================================================
 *
 *       Filename:  dog.c
 *
 *    Description:  dog class derived from animal base class.
 *
 * =============================================================================
 */
#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("doggggggggggggg");
    memcpy(&(dog->base), animal, sizeof(animal_t));

    dog->base.animal_ops->eat = eat;
    dog->base.animal_ops->walk = walk;
    dog->base.animal_ops->talk = talk;

    free(animal);
    return dog;
}

void dog_die(dog_t *dog)
{
    /* nothing to do here. */
}

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);
}
複製代碼

喵星人(cat 類) 的實現代碼:測試

複製代碼
/*
 * =============================================================================
 *
 *       Filename:  cat.h
 *
 *    Description:  cat class derived from animal base class.
 *
 * =============================================================================
 */
#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); // 獵兔犬 */
};

extern cat_t * cat_init();
extern void cat_die(cat_t * cat);
複製代碼
複製代碼
/*
 * =============================================================================
 *
 *       Filename:  cat.c
 *
 *    Description:  cat class derived from animal base class.
 * =============================================================================
 */
#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("cat");
    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;

    free(animal);
    return cat;
}

void cat_die(cat_t *cat)
{
    /* nothing to do here. */
}

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);
}
複製代碼

最後,測試代碼以下:spa

複製代碼
/*
 * =============================================================================
 *
 *       Filename:  main.c
 *
 *    Description:  main test.
 *
 *
 * =============================================================================
 */
#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(dog, "bones");
    animal_walk(dog, 5);
    animal_talk(dog, "wuang wuang wuang...");

    /* cat 類測試 */
    animal_eat(cat, "fish");
    animal_walk(cat, 3);
    animal_talk(cat, "miao miao miao...");

}
複製代碼

還有Makefile :.net

複製代碼
all:main

main:main.o dog.o cat.o animal-base.o
    gcc -o $@ $^

main.o:main.c

cat.o:cat.c

dog.o:dog.c

animal-base.o:animal-base.c

.PHONY:clean

clean:
    rm main main.o dog.o cat.o animal-base.o
複製代碼

最後執行結果爲:指針

複製代碼
I'm a dog, I eat bones
I'm a dog, I can jump 5 steps one time
I'm a dog, I talk my language wuang wuang wuang...
I'm a cat, I eat fish
I'm a cat, I can jump 3 steps one time
I'm a cat, I talk my language miao miao miao...
複製代碼
相關文章
相關標籤/搜索