C中的多态性

时间:2014-04-03 21:12:04

标签: c polymorphism

我正在编写一个C程序,我在其中定义了两种类型:

typedef struct {

    uint8_t array[32];
    /* struct A's members */
    ...

} A;

typedef struct {

    uint8_t array[32];
    /* struct B's members, different from A's */
    ...

} B;

现在我想建立一个能够管理这两种类型的数据结构,而不必为类型A写一个,假设两个都有一个uint8_t [32]作为它们的第一个成员。

我读了如何在C here中实现一种多态,我还读到here结构成员的顺序保证由程序员编写的编译器保留。

我提出了以下想法,如果我定义以下结构怎么办:

typedef struct {
    uint8_t array[32];
} Element;

并定义一个仅处理具有Element类型的数据的数据结构?做类似的事情是否安全:

void f(Element * e){
    int i;
    for(i = 0; i < 32; i++) do_something(e->array[i]);
}

...

A a;
B b;
...
f(((Element *)&a));
...
f(((Element *)&b));

乍一看它看起来不干净,但我想知道是否有任何保证不会破坏?

3 个答案:

答案 0 :(得分:1)

如果array始终是结构中的第一个,则只需通过转换指针即可访问它。不需要结构Element。您的数据结构可以存储void指针。

typedef struct {
    char array[32];
} A;

typedef struct {
    void* elements;
    size_t elementSize;
    size_t num;
} Vector;

char* getArrayPtr(Vector* v, int i) {
    return (char*)(v->elements) + v->elementSize*i;
}

int main()
{
    A* pa = malloc(10*sizeof(A));
    pa[3].array[0] = 's';
    Vector v;
    v.elements = pa;
    v.num = 10;
    v.elementSize = sizeof(A);
    printf("%s\n", getArrayPtr(&v, 3));
}

答案 1 :(得分:0)

但为什么没有直接使用数组的函数 void f(uint8_t array[32]){ int i; for(i = 0; i < 32; i++) do_something(array[i]); }

并像这样称呼它 f(a.array) f(b.array)

当你想要kepp时,

多态性是有意义的 a和b在某种容器中 并且你想迭代它们,但你不想关心它们是不同的类型。

答案 2 :(得分:0)

如果您不犯任何错误,这应该可以正常工作。指向A结构的指针可以转换为指向element结构的指针,只要它们具有公共前缀,对公共成员的访问就可以正常工作。

指向A结构的指针,然后转换为指向element结构的指针,也可以转换回指向A结构的指针,没有任何问题。如果element struct最初不是A结构,那么将指针强制转换回A将是未定义的行为。这需要您手动管理。

一个问题(我遇到过)是,gcc还允许你来回转换struct(不只是指向结构的指针),这是不受支持的按C标准。它似乎工作正常,直到你(我的)朋友试图将代码移植到另一个编译器(suncc),此时它将破坏。或者更确切地说,它甚至不会编译。