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

C语言中结构多态性的最佳方法,c,C,我正在写一个简单的2d向量对象。它将有x和y分量,以及长度、叉积等方法。问题是,我想让结构有许多可能的类型(char、int、float、double等)。我想知道,在设计方面,与对象交互的最佳选择是什么?以下是我目前正在考虑的: 1。让用户将向量对象传递给专门的函数,如: Vector2Dt_Dot(Vec2Dt* vector1, Vec2Dt* vector2); Vector2D_Dot(void* vector1, unsigned vector1_type, void* vecto

我正在写一个简单的2d向量对象。它将有x和y分量,以及长度、叉积等方法。问题是,我想让结构有许多可能的类型(char、int、float、double等)。我想知道,在设计方面,与对象交互的最佳选择是什么?以下是我目前正在考虑的:

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

Vector2Dt_Dot(Vec2Dt* vector1, Vec2Dt* vector2);
Vector2D_Dot(void* vector1, unsigned vector1_type, void* vector2, unsigned vector2_type);
其中“t”是向量的类型。然而,这种方法的问题是,它不允许不同类型的对象相互交互,所以我不能说计算浮点向量2D和双向量2D的点积。第二种方法,我倾向于:

2。让用户将向量对象及其类型作为空指针传递,如:

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


可能还有其他我不知道的解决方案,但这些是我目前正在考虑的。您觉得什么是最好的方法?

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

int  xyz(int a, ...);
此样式需要一个已定义的参数,在本例中为
a
,后跟任意数量的参数,这些参数的数据类型可以在运行时确定

请参见功能和对象:
va_列表
<代码>真空启动<代码>变量参数;和
va_end
,了解如何处理变量参数列表的完整说明


希望这有帮助。如果您对va_列表等有疑问,请询问。

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

#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
字段始终设置为正确的值(创建类型化向量时设置一次)

对于第二个想法,这种方法的优点是,不必在另一个变量中传递向量的类型,这会使使用向量变得单调乏味,并且容易出错


或者,您可以定义
类型
字段以包含指向函数指针结构的指针。您将为定义的每个类型化向量类型创建此函数指针结构的一个对象,并使用它查找要与给定向量一起使用的函数。这种方法将非常接近C++在引擎盖下的用法。

我实际所做的是如下:

我创建了一个基本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值转换为双精度值,从而避免泛型函数必须担心类型大小(如char和float)之间的差异。然后,每个派生类:

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

@如果问题被标记为
c
,而不是
c++
,请不要使用
void*
选项;有太多编译器无法捕捉到的错误(因为任何指针类型都可以在C或C++中转换为
void*
)。这个问题(一)有一个C++标记,并且更长的时间使用C++引用类型表示法。如果C++是相关的,考虑一下<代码>向量<代码>。我经常切换C和C++之间。如果它是C中的一个选项,我肯定会使用类似向量的接口。