В вышеприведённом примере полиморфизмом и не пахнет, т.к. мы используем разные функции для замены конструкторов с разным набором аргументов. Вот что получится если заюзать stdarg.h:
Code: Select all
typedef struct _MyClass
{
int id;
char str[10];
} MyClass;
void MyClass_cons(MyClass* this, int t, ...)
{
va_list a;
va_start(a,t);
if(t>=0)
{
*this->str = 0;
this->id = 0;
}
if(t>=1)
{
strncpy(this->str,va_arg(a,char*),10);
this->str[9] = 0;
}
if(t>=2)
{
this->id = va_arg(a,int);
}
va_end(a);
}
void MyClass_dest(MyClass* this)
{
}
void MyClass_Print(MyClass* this)
{
printf("id=%i str='%s'\n",this->id,this->str);
}
Тут мы воспользовались неким дополнительным аргументом t, который говорит функции-конструктору о том, какой набор аргументов следует использовать. Для простоты можно завести набор дефайнов для этого "конструктора":
Code: Select all
#define MY_CLASS_VOID 0
#define MY_CLASS_CHARP 1
#define MY_CLASS_CHARP_INT 2
Пример кода, использующий этот "класс":
Code: Select all
MyClass obj,*pobj;
MyClass_cons(&obj,MY_CLASS_CHARP,"test");
MyClass_Print(&obj);
MyClass_dest(&obj);
pobj = (MyClass*)malloc(sizeof(MyClass));
MyClass_cons(pobj,MY_CLASS_CHARP_INT,"test2",1);
MyClass_Print(pobj);
MyClass_dest(pobj);
free(pobj);
Для более компактного представления такого подхода можно соорудить вот такой вспомогательный инклуд:
Code: Select all
// file shaclass.h
#ifndef CLASS
#define CON(x,y) x##y
#define NEW(x) CON(new_,x)
#define DEL(x) CON(del_,x)
#define CONS(x) CON(x,_cons)
#define CONS_(x) CON(x,_cons_)
#define DEST(x) CON(x,_dest)
#define CLASS_BEGIN(x) typedef struct _##x {
#define CLASS_END(x) } x;
#define PUBLIC extern
#define METHOD(x,y) CON(x,_##y)
#define BEGIN(x) CLASS_BEGIN(x)
#define END(x) CLASS_END(x) \
PUBLIC void CONS(CLASS) (CLASS *this, int t, ...); \
PUBLIC void CONS_(CLASS) (CLASS* this, int t, va_list a); \
PUBLIC void DEST(CLASS) (CLASS *this); \
PUBLIC CLASS* NEW(CLASS) (int t, ...); \
PUBLIC void DEL(CLASS) (CLASS *this);
#else
void CONS(CLASS) (int t, ...)
{
va_list a;
va_start(a,t);
CONS_(CLASS) (p,t,a);
va_end(a);
}
CLASS* NEW(CLASS) (int t, ...)
{
CLASS* p;
va_list a;
va_start(a,t);
p = (CLASS*)malloc(sizeof(CLASS));
if(p!=NULL)
CONS_(CLASS) (p,t,a);
va_end(a);
return p;
}
void DEL(CLASS) (CLASS* p)
{
DEST(CLASS) (p);
free(p);
}
#endif
И пример кода:
Code: Select all
#include "shaclass.h"
#define CLASS MyClass
BEGIN(CLASS)
int id;
char str[10];
END(CLASS)
PUBLIC void METHOD(CLASS,Print) (CLASS *this);
#include "shaclass.h" // bodies
#define MY_CLASS_VOID 0
#define MY_CLASS_CHARP 1
#define MY_CLASS_CHARP_INT 2
void MyClass_cons_(MyClass* this, int t, va_list a)
{
if(t>=MY_CLASS_VOID)
{
*this->str = 0;
this->id = 0;
}
if(t>=MY_CLASS_CHARP)
{
strncpy(this->str,va_arg(a,char*),10);
this->str[9] = 0;
}
if(t>=MY_CLASS_CHARP_INT)
{
this->id = va_arg(a,int);
}
}
void MyClass_dest(MyClass* this)
{
}
void MyClass_Print(MyClass* this)
{
printf("id=%i str='%s'\n",this->id,this->str);
}
main()
{
MyClass obj,*pobj;
MyClass_cons(&obj,MY_CLASS_CHARP,"test");
MyClass_Print(&obj);
MyClass_dest(&obj);
pobj2 = new_MyClass(MY_CLASS_CHARP_INT,"test2",2);
MyClass_Print(pobj2);
del_MyClass(pobj2);
}