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

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

1.让用户将vector对象传递给专门的函数,例如:

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方面更紧凑,并且还解决了上述问题,但代价是一些额外的参数和类型安全性。

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

你可以做的是使用多态对象。 定义这样的结构:

 #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 ++所做的工作。

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

 int xyz(int a, ...); 

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

查看函数和对象: va_list ; va_start ; va_args ; 和va_end ,以获取有关如何处理变量参数列表的完整说明。

希望这可以帮助。 如果有关于va_list等的问题请询问。

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

我创建了一个基础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; 

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

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