网上找的C模拟面向对象多态的方法例子,有个错误解决不了,请大神指点
我测试使用环境是clang
运行代码会有"Here's the error, in new_.c, why can't invoke draw method in circle?"
附带说一下,我觉得这段代码并不符合经典的面向对象方式,但是,却显示出了指针的强大灵活。所以,希望这段代码能跑起来,请大神指点
--------------base_.h:
//2017/1/18
//http://
#ifndef BASE_H
#define BASE_H
#include <stdarg.h>
#include <stdlib.h>
struct Base{
size_t size;
void *(*constructor)(void *self, va_list *app);
void *(*deConstructor)(void *self);
void (*draw)(const void *self);
};
#endif
---point_.h---------------
//2017/1/18
//Point头文件(对外提供的接口):point.h
#ifndef POINT_H
#define POINT_H
extern const void *Point;///* 使用方法:new (Point, x, y); */
#endif
//Point内部头文件(外面看不到):point.r
#ifndef POINT_R
#define POINT_R
#include "base_.h"
struct PrivatePoint{
const void* Base;//继承,基类指针,放在第一个位置,const是防止修改
int x, y;
};
#endif
----------circle_.h---------
//2017/1/18
#ifndef CIRCLE_H
#define CIRCLE_H
#include "point_.h"
extern const void *Circle;
struct PrivateCircle{
struct PrivatePoint* point;//放在第一位,可表继承
int radius;
};
#endif
--------------new_.h
//2017/1/18
#ifndef NEW_H
#define NEW_H
#include <stdio.h>
void *new(const void* class, ...);
void delete(void *item);
void draw(const void* self);
#endif
-------------new_.c------------
//2017/1/18
#include <stdarg.h>
#include "new_.h"
#include "base_.h"
#include "circle_.h"
void *new(const void* _base, ...){
const struct Base* base = _base;
void *p = calloc(1, base->size);
*(const struct Base**)p = base;
if(base->constructor){
va_list ap;
va_start(ap, _base);
p = base->constructor(p, &ap);
va_end(ap);
}
return p;
}
void delete(void* self){
//why do I have to use cp here?
const struct Base** cp = self;
if(self && cp && (*cp)->deConstructor){
self = (*cp)->deConstructor(self);
}else{
printf("No DeConstructor\n");
}
free(self);
}
void draw(const void* self){
printf("new: draw\n");
//Is this right?
const struct Base *const* cp = self;
//Here's the error, why can't invoke draw method in circle?
if((*cp)->draw){
(*cp)->draw(self);
}else{
printf("Here's the error, in new_.c, why can't invoke draw method in circle?\n");
const struct PrivateCircle* pc = self;
printf("In new: draw: x = %d\n", pc->point->x);
printf("No Draw defined\n");
}
}
------point_.h---------
//2017/1/18
#include <stdarg.h>
#include <stdio.h>
#include "point_.h"
#include "new_.h"
static void* pointConstructor(void* _self, va_list *app){
struct PrivatePoint* self = _self;
self->x = va_arg(*app, int);
self->y = va_arg(*app, int);
return self;
}
static void pointDraw(const void* _self){
const struct PrivatePoint* self = _self;
printf("Point draw: %d, %d\n", self->x, self->y);
}
static const struct Base _Point = {
sizeof(struct PrivatePoint), pointConstructor, 0, pointDraw
};
//Check to make sure "type" itself is also an address
const void* Point = &_Point;
----------------circle_.c--------------
//2017/1/18
#include <stdio.h>
#include "point_.h"
#include "circle_.h"
#include "new_.h"
static void* circleConstructor(void* _self, va_list *app){
struct PrivateCircle* self = _self;
//must add "struct", otherwise: use of undeclared identifier 'PrivatePoint'
//must malloc first, otherwise: Segmentation fault (core dumped)
self->point = malloc(sizeof(struct PrivatePoint));
self->point->x = va_arg(*app, int);
self->point->y = va_arg(*app, int);
self->radius = va_arg(*app, int);
printf("Circle Constructor: %d, %d, %d\n", self->point->x, self->point->y, self->radius);
return self;
}
static void circleDraw(const void* _self){
const struct PrivateCircle* self = _self;
printf("Circle draw: %d, %d, %d\n", self->point->x, self->point->y, self->radius);
}
static const struct Base _Circle = {
sizeof(struct PrivateCircle), circleConstructor, 0, circleDraw
//sizeof(struct PrivateCircle), circleConstructor, 0, 0
};
const void* Circle = &_Circle;
------------main.c------------
//2017/1/18
#include "point_.h"
#include "circle_.h"
int main(){
void* p1 = new(Point, 1, 2);
void* p2 = new(Circle, 3, 4, 5);
draw(p1);
//Circle has error
draw(p2);
delete(p1);
// delete(p2);
}