简体   繁体   English

C与联盟的继承

[英]C Inheritance with Unions

I was reading somewhere about how some object oriented features can be implemented in C, and it has proven fairly useful. 我正在阅读有关如何在C中实现某些面向对象功能的内容,并且它已被证明非常有用。 In specific, I have been toying with the idea of inheritance. 具体来说,我一直在玩弄继承的想法。 Here is an example: 这是一个例子:

typedef struct Circle{
     int rad, x, y;
     //Other things...
} Circle;

typedef struct Entity{
    Circle body;
    //Entity-specific items...
} Entity;

This is simple, but it allows for something sneaky. 这很简单,但它允许偷偷摸摸的东西。 A pointer to an Entity is ALSO a pointer to a Circle because the first element of an Entity is always a Circle. 指向实体的指针也是指向Circle的指针,因为实体的第一个元素始终是Circle。 With this idea, we can construct the following function: 有了这个想法,我们可以构造以下功能:

int checkCircleCollision(Circle* one, Circle* two);

And call it as such: 并称之为:

Entity* myentity = createEntity(/* Things specific to my entity */);
Entity* myotherentity = createEntity(/* Different things */);
//Did they collide?
if (checkCircleCollision(myentity, myotherentity)){
    /* ... */
}

This is wonderful, but I ran into a problem. 这太棒了,但我遇到了一个问题。 What if I wanted some of my Entities to be rectangles, too? 如果我想让我的某些实体成为矩形怎么办? I have a solution, but I'd like confirmation that it will always work, no matter the compiler. 我有一个解决方案,但无论编译器如何,我都希望确认它始终有效。 My knowledge on unions is very limited. 我对工会的了解非常有限。

//Circle defined as above...
typedef struct Rectangle{
    int x, y, w, h;
    //Other things...
} Rectangle;

int checkRectangleCollision(Rectangle* one, Rectangle* two);
int checkRectangleCircleCollision(Rectangle* rect, Circle* circ);

typedef struct Entity{
     union{
         Rectangle rect;
         Circle circ;
     } shape;
     int type;
     //Entity things...
}

Is it now completely safe to assume that the first element of an Entity is either a Rectangle or a Circle , depending on its initialization? 现在可以完全安全地假设Entity的第一个元素是RectangleCircle ,具体取决于它的初始化吗? Furthermore, could it be used in any of the three functions described above? 此外,它可以用于上述三种功能中的任何一种吗? Bonus points for relevant quotes from the standard. 标准相关报价的奖励积分。 To be perfectly clear, I'd like to do this: 要非常清楚,我想这样做:

Entity* rectentity = createEntity(RECTANGLE, /* width/height/etc */);
Entity* circentity = createEntity(CIRCLE, /* rad/x/y/etc */ );
if (checkRectangleCircleCollision(rectentity, circentity)){
     /* ... */
}

Is it now completely safe to assume that the first element of an Entity is either a Rectangle or a Circle, depending on its initialization? 现在可以完全安全地假设实体的第一个元素是Rectangle或Circle,具体取决于它的初始化吗?

Yes. 是。

Bonus points for relevant quotes from the standard. 标准相关报价的奖励积分。

  • "A union type describes an overlapping nonempty set of member objects, each of which has an optionally specified name and possibly distinct type." “联合类型描述了一组重叠的非成员对象,每个成员对象都有一个可选的指定名称,可能还有不同的类型。” (C99, 6.2.5.20) (C99,6.2.5.20)

  • "A pointer to a union object, suitably converted, points to each of its members (or if a member is a bit- field, then to the unit in which it resides), and vice versa." “指向联合对象的指针,适当地转换,指向其每个成员(或者如果成员是位字段,则指向它所在的单位),反之亦然。” (6.7.2.1.14) (6.7.2.1.14)

A union , regardless of its active field, is always aligned on the same memory address. 无论其活动字段如何, union始终在同一内存地址上对齐。 For example, consider the following: 例如,请考虑以下事项:

#include <stdio.h>

int main(void)
{  
    union typeUnion
    {
        int i;
        float f; 
    } u;

    u.i = 5;    
    printf("%-4d (%p)\n", u.i, &u.i);

    u.f = 3.14;
    printf("%.2f (%p)", u.f, &u.f);

    return 0;
}

Output on my machine: 我机器上的输出:

5    (0x22aac0) 
3.14 (0x22aac0)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM