typedef struct object *BaseObj;
typedef struct sclass *Class;
typedef void (*CloneFctn)(BaseObj s, BaseObj clo);
typedef const char * (*SpeakFctn)(BaseObj s);
typedef void (*DestroyFctn)(BaseObj s);

typedef struct sclass {
    size_t csize;		
    const char  *cname;		
    Class  parent;		

    CloneFctn clone;		
    SpeakFctn speak;		
    DestroyFctn del;		
} sClass;

typedef struct object {
    Class class;
} SObject;

static 
BaseObj obj_copy( BaseObj s, Class c )
{
    BaseObj clo;
    if (c->parent) 
        clo = obj_copy( s, c->parent);
    else 
        clo = malloc( s->class->csize );

    if (clo)
        c->clone( s, clo );
    return clo;
}

static
void obj_del( BaseObj s, Class c )
{
    if (c->del)
        c->del(s);
    if (c->parent)
        obj_del( s, c->parent);
    else
        free(s);
}

BaseObj ObjClone( BaseObj s )
{ return obj_copy( s, s->class ); }

const char * ObjSpeak( BaseObj s )
{ 
    return s->class->speak(s); 
}

void ObjDestroy( BaseObj s )
{ if (s) obj_del( s, s->class ); }


static
void baseClone( BaseObj s, BaseObj clone)
{  
    clone->class = s->class;
}

static
const char *baseSpeak(BaseObj s)
{
    return ;
}

sClass boc = { sizeof(SObject), , NULL, 
    &baseClone, &baseSpeak, NULL };
Class BaseObjClass = &boc;




typedef struct sDogPart {
    double weight;
    char color[32];
    char name[24];
} DogPart;

typedef struct sDog *Dog;

struct sDog {
    Class   class;		
    DogPart dog;
};

static
void dogClone( BaseObj s, BaseObj c)
{  
    Dog src = (Dog)s;
    Dog clone = (Dog)c;
    clone->dog = src->dog;	
}

static
const char *dogSpeak( BaseObj s)
{
    Dog d = (Dog)s;
    static char  response[90];
    sprintf(response, , 
            d->dog.name, d->dog.color, d->class->cname);
    return response;
}


sClass dogc = { sizeof(struct sDog), , &boc,
    &dogClone, &dogSpeak, NULL };
Class DogClass = &dogc;

BaseObj NewDog( const char *name, const char *color, double weight )
{
    Dog dog = malloc(DogClass->csize);
    if (dog) {
        DogPart *dogp = &dog->dog;
        dog->class = DogClass;
        dogp->weight = weight;
        strncpy(dogp->name, name, 23);
        strncpy(dogp->color, color, 31);
    }
    return (BaseObj)dog;
}




typedef struct sFerretPart {
    char color[32];
    char name[24];
    int  age;
} FerretPart;

typedef struct sFerret *Ferret;

struct sFerret {
    Class   class;		
    FerretPart ferret;
};

static
void ferretClone( BaseObj s, BaseObj c)
{  
    Ferret src = (Ferret)s;
    Ferret clone = (Ferret)c;
    clone->ferret = src->ferret;  
}

static
const char *ferretSpeak(BaseObj s)
{
    Ferret f = (Ferret)s;
    static char  response[90];
    sprintf(response, , 
            f->ferret.name, f->ferret.age, f->ferret.color,
            f->class->cname);
    return response;
}

sClass ferretc = { sizeof(struct sFerret), , &boc, 
    &ferretClone, &ferretSpeak, NULL };
Class FerretClass = &ferretc;

BaseObj NewFerret( const char *name, const char *color, int age )
{
    Ferret ferret = malloc(FerretClass->csize);
    if (ferret) {
        FerretPart *ferretp = &(ferret->ferret);
        ferret->class = FerretClass;
        strncpy(ferretp->name, name, 23);
        strncpy(ferretp->color, color, 31);
        ferretp->age = age;
    }
    return (BaseObj)ferret;
}



int main()
{
    BaseObj  o1;
    BaseObj  kara = NewFerret( , , 15 );
    BaseObj  bruce = NewDog(, , 85.0 );
    printf();

    o1 = ObjClone(kara );
    printf(, ObjSpeak(o1));
    printf(, ObjSpeak(kara));
    ObjDestroy(o1);

    o1 = ObjClone(bruce );
    strncpy(((Dog)o1)->dog.name, , 23);
    printf(, ObjSpeak(o1));
    printf(, ObjSpeak(bruce));
    ObjDestroy(o1);
    return 0;
}