【问题标题】:Subtyping with function pointers, structs, unions, and enums使用函数指针、结构、联合和枚举进行子类型化
【发布时间】:2015-05-04 02:12:19
【问题描述】:

前言:是的,这是作业。上周左右我一直在研究它,谷歌搜索没有帮助。我不是在找人来帮我完成作业,我更关心的是理解材料,我只是在寻找任何建设性的批评或朝着正确方向推动。

我有 3 个形状结构(圆形、三角形和矩形)、3 个形状结构的联合、一个函数指针结构、一个形状枚举和一个以上所有形状的结构(联合、形状类型和函数指针)。

问题:我需要完成子类型/超类型以允许驱动程序在不知道其详细信息的情况下对 Shapes 进行操作。我相信我已经完成了大部分框架,但对函数指针和使用 ShapeType 枚举和 Shape 结构来实现它们有点迷失。

prototypes.h

#include <my_struct.h>

void InitializeCircle(struct Shape *, double radius, double origin, double originY);
void InitializeRectangle(struct Shape *, double minX, double maxX, double minY, double maxY);
void InitializeTriangle(struct Shape *, Triangle *, double pt1X, double pt2X, double minY, double maxY);

double GetCircleArea(struct Shape *);
double GetCircleArea(struct Shape *);
double GetTriangleArea(struct Shape *);

void GetCircleBoundingBox(struct Shape *, double *);
void GetRectangleBoundingBox(struct Shape *, double *);
void GetTriangleBoundingBox(struct Shape *, double *);

my_struct.h

// DEFINITIONS FOR THE THREE SHAPES:
typedef struct {
    double radius, origin, originY, area;
} Circle;

typedef struct {
    double pt1X, pt2X, minY, maxY, area;
} Triangle;

typedef struct {
    double minX, maxX, minY, maxY, area;
} Rectangle;


// SUBTYPING/SUPERTYPING:
struct Shape;   // Defined later

typedef struct {
    // Pointers to functions -> two data members: GetArea & GetBoundingBox
    double (*GetArea)(struct Shape *);
    GetArea = // NEED TO IMPLEMENT

    double (*GetBoundingBox)(struct Shape *, double *bbox);
    GetBoudingBox = // NEED TO IMPLEMENT

} FunctionTable;

typedef union {
    // Shape structs:
    Circle c;
    Triangle t;
    Rectangle r;
} ShapeUnion;

typedef enum {
    // Identifies the 3 types
    Circle,
    Rectangle,
    Triangle
} ShapeType;

typedef struct {
    ShapeUnion su;
    ShapeType st;
    FunctionTable ft;
} Shape;

my_struct.c

/* This file should contain the 9 functions defined in prototypes.h */

#include <prototypes.h>

// Initialize Structs
void InitializeCircle(struct Shape *c, double r, double o, double oY) {
    c->radius = r;
    c->origin = o;
    c->originY = oY;
}
void InitializeRectangle(struct Shape *r, double miX, double maX, double miY, double maY) {
    r->minX = miX;
    r->maxX = maX;
    r->minY = miY;
    r->maxY = maY;
}
void InitializeTriangle(struct Shape *t, double p1X, double p2X, double miY, double maY) {
    t->pt1X = p1X;
    t->pt2X = p2X;
    t->minY = miY;
    t->maxY = maY;
}

// Get Area
double GetCircleArea(struct Shape *c) {
    c->area = 3.14159*c->radius*c->radius;
    return c->area;
}
double GetRectangleArea(struct Shape *r) {
    r->area = ((r->maxX-r->minX)*(r->maxY-r->minY));
    return r->area;
}
double GetTriangleArea(struct Shape *t) {
    t->area = (((t->pt2X-t->pt1X)*(t->maxY-t->minY))/2);
    return t->area;
}

// Get Bounding Box
void GetCircleBoundingBox(struct Shape *c, double *bbox) {
    bbox[0] = c->origin-c->radius;  // lower left corner
    bbox[1] = c->origin+c->radius;  // lower right corner
    bbox[2] = c->originY-c->radius; // upper left corner
    bbox[3] = c->originY+c->radius; // upper right corner
}
void GetRectangleBoundingBox(struct Shape *r, double *bbox) {
    bbox[0] = r->minX;
    bbox[1] = r->maxX;
    bbox[2] = r->minY;
    bbox[3] = r->maxY;
}
void GetTriangleBoundingBox(struct Shape *t, double *bbox) {
    bbox[0] = t->pt1X;  // minX
    bbox[1] = t->pt2X;  // maxX
    bbox[2] = 0;        // minY
    bbox[3] = t->maxY;  // maxY
}

driver.c

#include <prototypes.h>
#include <stdio.h>

int main()
{
    struct Shape shapes[9];
    int i;

    InitializeCircle(shapes+0, 1, 0, 0);
    InitializeCircle(shapes+1, 1.5, 6, 8);
    InitializeCircle(shapes+2, 0.5, -3, 4);

    InitializeRectangle(shapes+3, 0, 1, 0, 1);
    InitializeRectangle(shapes+4, 1, 1.1, 10, 20);
    InitializeRectangle(shapes+5, 1.5, 3.5, 10, 12);

    InitializeTriangle(shapes+6, 0, 1, 0, 1);
    InitializeTriangle(shapes+7, 0, 1, 0, 0.1);
    InitializeTriangle(shapes+8, 0, 10, 0, 50);

    for (i = 0 ; i < 9 ; i++)
    {
        double bbox[4];
        printf("Shape %d\n", i);
        printf("\tArea: %f\n", shapes[i].ft.GetArea(shapes+i));
        shapes[i].ft.GetBoundingBox(shapes+i, bbox);
        printf("\tBbox: %f-%f, %f-%f\n", bbox[0], bbox[1], bbox[2], bbox[3]);
    }
}

任何见解都将/将不胜感激。再说一次,我不是在找人帮我做作业,我只是希望能克服这个障碍。

【问题讨论】:

  • 不能用InitializeXYZ中的相关函数指针设置函数表吗?
  • @AlanAu 感谢您的意见!我相信我可以,但是这个任务如果集中在我的 FunctionTable 结构中实现函数指针“GetArea”和“GetBoundingBox”。不幸的是,没有办法解决这个问题。
  • 但是你不能将代码体直接放入结构定义中。所以你必须在别处实现这些功能。然后在 Initialize 函数中,使用指向已实现的实际函数的指针填充 FunctionTable 结构成员。除非我完全误解了你的要求。
  • 请注意struct Shape;typedef struct {...} Shape; 不是同一类型。后者需要typedef struct Shape {...} Shape;

标签: c struct enums unions subtyping


【解决方案1】:

您需要为每种类型定义函数表:

// This is global, and used for all circle types. 
// Could be declared 'static' if table and init functions are in the same file.
FunctionTable const CircleFuncs = {
    GetCircleArea,
    GetCircleBoundingBox
};

由于同一类型的所有形状都可以共享表格,因此我们只需要指针即可:

typedef struct Shape { // <- note the fixed type name also
    ShapeUnion su;
    ShapeType st;
    FunctionTable const * ft;
} Shape;

初始化函数应该将表格分配给形状:

void InitializeCircle(struct Shape *c, double r, double o, double oY) {
    /* other inits here*/
    c->ft = &CircleFuncs;
}

【讨论】:

    猜你喜欢
    • 2013-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-22
    相关资源
    最近更新 更多