Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.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_Inheritance_Unions - Fatal编程技术网

C带并集的继承

C带并集的继承,c,inheritance,unions,C,Inheritance,Unions,我在某个地方读到了一些关于如何用C实现一些面向对象的特性的文章,事实证明它是相当有用的。具体来说,我一直在玩弄继承的想法。以下是一个例子: typedef struct Circle{ int rad, x, y; //Other things... } Circle; typedef struct Entity{ Circle body; //Entity-specific items... } Entity; 这很简单,但它允许一些鬼鬼祟祟的东西。指向

我在某个地方读到了一些关于如何用C实现一些面向对象的特性的文章,事实证明它是相当有用的。具体来说,我一直在玩弄继承的想法。以下是一个例子:

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

typedef struct Entity{
    Circle body;
    //Entity-specific items...
} Entity;
这很简单,但它允许一些鬼鬼祟祟的东西。指向实体的指针也是指向圆的指针,因为实体的第一个元素始终是圆。有了这个想法,我们可以构造以下函数:

int checkCircleCollision(Circle* one, Circle* two);
并称之为:

Entity* myentity = createEntity(/* Things specific to my entity */);
Entity* myotherentity = createEntity(/* Different things */);
//Did they collide?
if (checkCircleCollision(myentity, myotherentity)){
    /* ... */
}
这很好,但我遇到了一个问题。如果我希望我的一些实体也是矩形呢?我有一个解决方案,但我想确认它将始终工作,无论编译器。我对工会的了解非常有限

//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...
}
现在是否可以完全安全地假设实体的第一个元素是矩形或圆形,具体取决于其初始化?此外,它是否可以用于上述三种功能中的任何一种?标准中相关引用的加分。非常清楚地说,我想这样做:

Entity* rectentity = createEntity(RECTANGLE, /* width/height/etc */);
Entity* circentity = createEntity(CIRCLE, /* rad/x/y/etc */ );
if (checkRectangleCircleCollision(rectentity, circentity)){
     /* ... */
}
现在是否可以完全安全地假设实体的第一个元素是矩形或圆形,具体取决于其初始化

标准中相关引用的加分

联合类型描述了一组重叠的非空成员对象,每个对象都有一个可选的指定名称和可能不同的类型。C99,6.2.5.20

一个指向联合对象的指针,经过适当转换后,指向它的每个成员,或者如果一个成员是位字段,则指向它所在的单元,反之亦然。6.7.2.1.14

联合,不管它的活动字段是什么,总是在同一个内存地址上对齐。例如,考虑以下内容:

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

类型双关可能是您要搜索的关键字。如果您的类型位于结构的开头而不是底部,则调试会更容易。每当向联合体添加新结构时,类型的位置都会移动。如果您使用的调试器没有源代码,那么将类型放在顶部会有所帮助。@brainseel Entity是circle和rectangle的父类?@self。对@cup它不能位于顶部,因为这样一来,指向实体的指针也是指向int命名类型的指针,而不是指向联合的指针。@brainseel不在实体结构中嵌入子结构,而是执行相反的操作。仅使用实体结构自身的成员声明实体结构。然后,当您想要添加一个圆时,创建一个圆结构,并在圆结构中声明一个实体结构。这样,你就不必和类型打交道了。每个子项在结构的开头都有它的父项,而不是每个父项在一个联合中都有多个可能的子项。@FiddlingBits Awww,那么我今天就没有任何奖金了。。。我必须承认,我的文档文件夹里有标准的PDF!非常感谢。这正是我想要的。你从哪里得到这个PDF?另外,我对奖励积分也不是那么挑剔。记住会让人印象深刻。我得给你买块饼干。@brainseel不客气。指向实体的指针是指向结构的指针,而不是指向联合的指针。本标准中有一个不同的段落。并且,当指向结构的经过适当转换的指针指向其第一个成员时,如果该成员是一个并集,则新指针在再次转换为指向某一类型的成员时,将指向该成员,不清楚从指向结构的指针到指向结构的第一个成员的指针的单个转换是否完全由C标准定义。@EricPostIschil指向实体的指针是指向结构的指针,而不是指向联合的指针。本标准中有一个不同的段落是的,如果你读了这个问题,你会发现OP已经意识到指向一个实体的指针也是指向一个圆的指针,因为一个实体的第一个元素总是一个圆。此外,我没有对所需的转换次数做出任何断言。我只回答了这个问题。如果你是对的,那么两个演员是必要的,使其工作,这是好的,我没有说它不是这样的。这直接和迅速地解决了我的问题。非常感谢。
5    (0x22aac0) 
3.14 (0x22aac0)