多態,面向接口編程等設計方法並沒有綁定到任何特定的語言上,使用純C也可以實現簡單的多態概念。下面給出一個非常簡單粗糙的例子,只為說明概念。
父類Animal定義
文件:animal.h
#ifndef ANIMAL_H
#define ANIMAL_H
/* 方法表, 類似於C++的虛函數表 */
typedef struct vtable vtable;
struct vtable
{
void (*eat)();
void (*bite)();
};
typedef struct Animal Animal;
struct Animal
{
const vtable* _vptr; /* 每一個對象都有一個指向虛表的指針*/
};
/*
如果不用虛表的話,每個對象都要包含所有的接口函數指針, 而實際上所有同類型對象的這些指針的值是相同的,造成內存浪費。
接口函數是和類型一對一的,而不是和對象一對一。
struct Animal
{
void (*eat)();
void (*bite)();
};
*/
#endif
子類Dog,文件dog.h
#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
#include
#include
#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
#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
#include
#include
#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
#include
#include "animal.h"
#include "cat.h"
#include "dog.h"
void ShowBite(Animal* pAnimal)
{
pAnimal->_vptr->bite();
}
void main()
{
ShowBite(create_dog());
ShowBite(create_cat());
}