C语言中结构多态的最佳方法

时间:2013-08-24 18:54:52

标签: c

我正在写一个简单的2d矢量对象。它将具有x和y组件,以及长度,交叉产品等方法。问题是,我希望结构具有许多可能的类型(char,int,float,double等)。我想知道什么是最好的选择,设计明智,与对象互动?这是我正在考虑的内容:

1。让用户将矢量对象传递给专门的函数,例如:

Vector2Dt_Dot(Vec2Dt* vector1, Vec2Dt* vector2);

其中't'是向量的类型。然而,这种方法的问题在于它不允许不同类型相互交互,所以我不能说计算float vector2d和double vector2d的点积。第二种方法,以及我倾向于:

2。让用户将矢量对象及其类型传递为void指针,例如:

Vector2D_Dot(void* vector1, unsigned vector1_type, void* vector2, unsigned vector2_type);
显然,这种方法在API方面更紧凑,并且还解决了上述问题,但代价是一些额外的参数和类型安全性。

可能还有其他我不了解的解决方案,但这些是我正在考虑的解决方案。您认为最好的方法是什么?

3 个答案:

答案 0 :(得分:15)

您可以做的是使用多态对象。定义如下结构:

#define INT_TYPE 0
#define DOUBLE_TYPE 1
//more type constants

typedef struct Vector2D {
    int type;
} Vector2D;

typedef struct Vector2D_int {
    Vector2D super;
    int x, y;
} Vector2D_int;

typedef struct Vector2D_double {
    Vector2D super;
    double x, y;
} Vector2D_double;

//more typed vector structures

然后,您可以编写函数来接受Vector2D指针,检查它们各自的类型字段并将它们转换为适当的类型变量以访问有效负载数据。

double Vector2D_length(const Vector2D* vector) {
    if(vector->type == TYPE_INT) {
        const Vector2D_int* intVector = (Vector2D_int*)vector;
        return sqrt(intVector->x * intVector->x + intVector->y * intVector->y);
    }
    if(vector->type == TYPE_DOUBLE) {
        const Vector2D_double* doubleVector = (Vector2D_double*)vector;
        return sqrt(doubleVector->x * doubleVector->x + doubleVector->y * doubleVector->y);
    }
    //other cases follow
}

这是手工编码的多态性。您需要确保的是,type字段始终设置为正确的值(在创建类型向量时设置一次)。

这种方法对你的第二个想法的好处是,你不必在另一个变量中传递向量的类型,这会使你的向量变得乏味且容易出错。

作为替代方法,您可以定义type字段以包含指向函数指针结构的指针。您将为每个键入的Vector类型创建此函数指针结构的一个对象,并使用它来查找与给定向量一起使用的函数。这种方法非常接近C ++所做的工作。

答案 1 :(得分:3)

您可以使用变量参数列表,其原型编码,例如:

int  xyz(int a, ...);

此样式需要一个已定义的参数,在此示例中为a,后跟任意数量的参数,其数据类型可在运行时确定。

查看功能和对象:va_list; va_start; va_args;和va_end,以获得有关如何处理变量参数列表的完整描述。

希望这会有所帮助。如果有关于va_list等的问题,请询问。

答案 2 :(得分:0)

我实际使用的是以下内容:

我创建了一个基础Vector2D类,具有以下布局:

struct Vector2D_Base;
typedef struct Vector2D_Base{
    M_double (*Vector2D_Get_X)(struct Vector2D_Base* vec);
    M_double (*Vector2D_Get_Y)(struct Vector2D_Base* vec);
} Vector2D;

正如你所看到的,这允许泛型向量函数调用它们来获取派生类的x和y值转换为double,这可以防止泛型函数不必担心char和float等类型的大小之间的差异。然后是每个派生类:

#define DEFINE_VECTOR2D(type, name)\
typedef struct{\
Vector2D_Base vec_base;\
type x, y;\
} Vector2D##name\