您的位置:首页 > 编程语言 > C语言/C++

纯C语言简单模拟C++的虚函数表

2016-02-15 18:14 507 查看
[code]多态,面向接口编程等设计方法并没有绑定到任何特定的语言上,使用纯C也可以实现简单的多态概念。下面给出一个非常简单粗糙的例子,只为说明概念。


父类Animal定义

文件:animal.h

[code]#ifndef ANIMAL_H
#define ANIMAL_H

/* 方法表, 类似于C++的虚函数表 */
typedef struct vtable vtable;
struct vtable
{
    void (*eat)();
    void (*bite)();
};

typedef struct Animal Animal;
struct Animal
{
    vtable* _vptr;  /* 每一个对象都有一个指向虚表的指针*/
};

/*
 如果不用虚表的话,每个对象都要包含所有的接口函数指针, 而实际上所有同类型对象的这些指针的值是相同的,造成内存浪费。
 接口函数是和类型一对一的,而不是和对象一对一。

struct Animal
{
    void (*eat)();
    void (*bite)();
};

*/

#endif


子类Dog,文件dog.h

[code]#ifndef DOG_H
#define DOG_H

#include "animal.h"

typedef struct Dog Dog;
struct Dog
{
    Animal base_obj;
    int x;
};

Animal* create_dog();

#endif


dog.c

[code]#include <stdio.h>
#include <stdlib.h>
#include "dog.h"

static void dog_eat()
{
    printf("dog_eat()\n");
};

static void dog_bite()
{
    printf("dog_bite()\n");
};

/* 虚表是在编译时确定的 */
static const vtable dog_vtable = {
    dog_eat,
    dog_bite
};

Animal* create_dog()
{
    Dog * pDog = malloc(sizeof(Dog));
    if(pDog){
        pDog->base_obj._vptr = &dog_vtable; /*运行时,绑定虚表指针*/
        pDog->x = 0;
    }
    return (Animal*)pDog;
}


另一个子类Cat, 文件cat.h

[code]#ifndef CAT_H
#define CAT_H

#include "animal.h"

typedef struct Cat Cat;
struct Cat
{
    Animal base_obj;
    float y;
};

Animal* create_cat();

#endif


cat.c

[code]#include <stdio.h>
#include <stdlib.h>
#include "animal.h"
#include "cat.h"

static void cat_eat()
{
    printf("cat_eat()\n");
};

static void cat_bite()
{
    printf("cat_bite()\n");
};

static const vtable cat_vtable = {
    cat_eat,
    cat_bite
};

Animal* create_cat()
{
    Cat * pCat = malloc(sizeof(Cat));
    if(pCat){
        pCat->base_obj._vptr = &cat_vtable;
        pCat->y = 0.0;
    }
    return (Animal*)pCat;
}


主文件 main.c

[code]#include <stdio.h>
#include "animal.h"
#include "cat.h"
#include "dog.h"

void ShowBite(Animal* pAnimal)
{
    pAnimal->_vptr->bite();
}
void main()
{
    ShowBite(create_dog());
    ShowBite(create_cat());

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: