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