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

Sho*_*wav 9 c

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

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

Vector2Dt_Dot(Vec2Dt* vector1, Vec2Dt* vector2);
Run Code Online (Sandbox Code Playgroud)

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

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

Vector2D_Dot(void* vector1, unsigned vector1_type, void* vector2, unsigned vector2_type);
Run Code Online (Sandbox Code Playgroud)

显然,这种方法在API方面更紧凑,并且还解决了上述问题,但代价是一些额外的参数和类型安全性.

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

cma*_*ter 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
Run Code Online (Sandbox Code Playgroud)

然后,您可以编写函数来接受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
}
Run Code Online (Sandbox Code Playgroud)

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

这种方法对你的第二个想法的优点是,你不必在另一个变量中传递向量的类型,这将使​​你的向量使用繁琐且容易出错.

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