Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C中的一类多态性_C_Polymorphism - Fatal编程技术网

C中的一类多态性

C中的一类多态性,c,polymorphism,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编写一个,为类型

我正在编写一个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编写一个,为类型B编写一个,假设两者都有一个uint8_t[32]作为其第一个成员

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

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

typedef struct {
    uint8_t array[32];
} 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));
void f(元素*e){
int i;
对于(i=0;i<32;i++)做某事(e->array[i]);
}
...
A A;
B B;
...
f(((元素*)&a));
...
f(((元素*)&b));

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

但是为什么不使用一个直接与数组一起工作的函数呢

void f(uint8_t数组[32]){
int i;
对于(i=0;i<32;i++)do_something(数组[i]);
}

这样称呼它

f(a.阵列)
f(b.阵列)

当您想要kepp时,多态性是有意义的 a和b在某种容器中
你想重复它们,但你不想在意它们是不同的类型。

如果你知道,不犯任何错误,这应该很好。指向
A
struct的指针可以转换为指向
元素的指针,只要它们有一个公共前缀,就可以访问公共成员

指向
A
结构的指针,然后将其转换为指向
元素的指针
结构,也可以将其转换回指向
A
结构的指针,而不会出现任何问题。如果
element
struct最初不是
A
struct,那么将指针投射回
A
将是未定义的行为。这需要手动管理


我遇到的一个问题是,gcc还允许您来回转换
struct
(不仅仅是指向struct的指针),这是C标准不支持的。在您(我的)朋友尝试将代码移植到另一个编译器(suncc)之前,它似乎可以正常工作,此时代码将中断。或者更确切地说,它甚至不会编译。

如果
array
始终是结构中的第一个,您可以通过强制转换指针来访问它。不需要结构
元素
。数据结构可以存储空指针

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));
}

如果你想要的是多态结构,你有没有理由使用C++?“为工作使用正确的工具”这句话浮现在脑海中。
dou\u something()
的签名是什么?它仅限于访问一个字节还是数组?@EricLippert你说得对,但我以前从来没有使用过C++,而且这个代码是我很久以前用C开始的一个项目的一部分,而没有清楚地知道我将要解决的长期问题。为什么不<代码> A<代码>和代码> B<代码>直接将<代码>元素< /代码>直接作为他们的第一个成员?哦,不,你的建议没有错。那很好。这更多的是了解你的目标,并与其他可能性进行比较。对不起,也许我的问题不够清楚。我需要一个数据结构,它可以作为任何类型的容器,该类型的第一个成员是uint8_t[32]数组。我提出的数据结构将把它的元素存储为(元素*)类对象。在我看来,你要做的是使用C,但仍然保留一些C++类型的安全文件…由于这是C,您可以将对象存储为void*,并且您知道它们以uint8_t数组[32]开始,并将其转换为void*。。。或者你可以直接访问内存。。。没有人会介意或关心。。。最后,这只是记忆耶,这就是重点,我保证访问
((Element*)&a)->array
将始终与访问
a.array
相同吗?我想你没有。为了弥补这一点:)谢谢。我搔了搔头,差点把自己秃了一块P