Par fonction virtuelle on entend redéfinir une méthode dans une classe fille.
Pour simuler cela, tu te fais une structure qui comporte des pointeurs sur fonction et des éléments "normaux" (ce qu'on appelle une vtable pour "virtual table", que le C++ gère automatiquement).
Ensuite, tu fais une deuxième structure qui possède au moins les mêmes éléments, en plus d'avoir des vtables.
Lorsque tu castes, si tu as bien fait les choses, même en utilisant une classe mère, ça appellera bien une méthode de la classe enfant.
C'est très dur à expliquer, voici un exemple, simplifié pour illustrer mes dires:
#include <stdio.h>
#include <stdlib.h>
typedef void (*VirtualFunctionPointer)(void*);
typedef struct
{
VirtualFunctionPointer pFunc;
} VTable;
struct Mother;
struct Daughter;
typedef struct
{
VTable* pVTable;
int i;
float f;
} Mother;
typedef struct
{
VTable* pVTable;
int i;
float f;
char c;
} Daughter;
void mother_kikoo(void* this)
{
printf("Mother: Kikoo %p\n", this);
}
void mother_display(void* this)
{
Mother* _this = this;
printf("Mother: %i %f\n", _this->i, _this->f);
}
void daughter_display(void* this)
{
Daughter* _this = this;
mother_display((Mother*)this);
printf("Daughter: %i %f %c\n", _this->i, _this->f, _this->c);
}
VTable VTableArrayForMother[] =
{
{ (VirtualFunctionPointer) mother_display },
{ (VirtualFunctionPointer) mother_kikoo }
};
VTable VTableArrayForDaughter[] =
{
{ (VirtualFunctionPointer) daughter_display },
{ (VirtualFunctionPointer) mother_kikoo }
};
Mother* new_Mother(void)
{
Mother* this = NULL;
this = (Mother*) malloc(1 * sizeof (Mother));
this->pVTable = VTableArrayForMother;
return this;
}
Daughter* new_Daughter(void)
{
Daughter* this = NULL;
this = (Daughter*) malloc(1 * sizeof (Daughter));
this->pVTable = VTableArrayForDaughter;
return this;
}
int main(void)
{
Mother* klass = new_Mother();
Mother* klass2 = (Mother*) new_Daughter();
klass->i = 7;
klass->f = 34.5;
(klass->pVTable[0].pFunc)(klass);
(klass->pVTable[1].pFunc)(klass);
free(klass);
printf("\n\n");
klass2->i = 89;
klass2->f = 103.34;
(klass2->pVTable[0].pFunc)(klass2);
(klass2->pVTable[1].pFunc)(klass2);
free(klass2);
return 0;
}