我有一个关于工会我仍然不理解的问题。我已经阅读了很多他们的用途,并且在大多数情况下可以看到它们如何有用并理解它们。我已经看到他们可以提供原始的“C风格”多态性。我在几个网站上看到的这个例子是SDL的事件联盟:
typedef union {
Uint8 type;
SDL_ActiveEvent active;
SDL_KeyboardEvent key;
SDL_MouseMotionEvent motion;
SDL_MouseButtonEvent button;
SDL_JoyAxisEvent jaxis;
SDL_JoyBallEvent jball;
SDL_JoyHatEvent jhat;
SDL_JoyButtonEvent jbutton;
SDL_ResizeEvent resize;
SDL_ExposeEvent expose;
SDL_QuitEvent quit;
SDL_UserEvent user;
SDL_SysWMEvent syswm;
} SDL_Event;
我无法理解的是,那里的“类型”成员如何与事件类型共存?这些是不是每个只允许一次存在一个,因为它们占据相同的记忆区域?联盟不会在任何时候作为一种类型或一种事件存在吗?
据我所知,每个事件实际上都是一个带有类型成员的结构,例如:
// SDL_MouseButtonEvent
typedef struct{
Uint8 type;
Uint8 button;
Uint8 state;
Uint16 x, y;
} SDL_MouseButtonEvent;
这有什么意义?这是否以某种方式允许联合的类型成员表示联合当前的任何结构的类型?当一个联盟的每个成员除了一个结构并且每个结构包含那个成员时,会发生这种奇怪的效果吗?
您可以在不知道对象是哪个结构的情况下访问struct成员吗?
谢谢!
答案 0 :(得分:8)
如果每个事件类型都有Uint8
作为其第一个数据成员,那么type
的{{1}}成员只是方便。
使用联合的一般规则是,您只能使用您编写的最后一个数据成员访问联合中的数据。因此,如果您上次写信给union
,则接下来无法从active
读取。
此规则的一个例外是,如果联盟的多个成员共享相同的前缀(如果它们的第一个数据成员相同),则可以通过共享的联合的任何数据成员访问该前缀前缀。所以,在这里,你可以引用key
或active.type
,无论联合的哪个数据成员是活动的,它都可以工作。
key.type
type
成员只是一种方便的快捷方式,可让您访问该SDL_Event
字段,而无需将其限定为type
或event_object.active.type
。您可以使用event_object.key.type
。
答案 1 :(得分:6)
让我们来看看联盟是如何在记忆中铺设的:
Address: Uint8 MouseButtonEvent KeyboardEvent
x+0x0 type type type
x+0x1 - button ?
x+0x2 - state ?
...
恰好恰好type
成员排队,所以无论它是什么类型,以Uint8
访问联合将产生事件的实际类型。
答案 2 :(得分:0)
如果每个SDL_xyz结构的前几个字节都是它们自己的类型字段,这意味着当union包含其中一个对象时,union的前几个字节与SDL结构的前几个字节相同 - 即类型字段。
union不包含两者,它只包含SDL对象,其第一个成员恰好在类型,大小和位置上与'type'字段重合。
答案 3 :(得分:0)
标准要求C / C ++中的联盟符合它们包含的最严格类型。此外,由于结构的成员不能重新排序,并且由于当前标准的要求(在C ++ 0x中更改),联合仅包含POD类型,因此联盟的类型成员映射到类型成员中它包含的struct decks。
答案 4 :(得分:0)
就联合而言,结构和原始类型之间没有真正的区别。 SDL_MouseButtonEven
结构只是一堆一个接一个的类型
联盟的type
成员取代了事件结构的type
成员。用图形表示,它看起来像这样:
SDL_Event union:
type: |--------|
motion: |--type--|-button-|--state-|-------x--------|-------y--------|
active: |--type--|----------something-else-of-another-event--|
key: |--type--|--maybe-a-smaller-event-|
... etc'
答案 5 :(得分:0)
[编辑,感谢詹姆斯的评论。]
标准对工会做出了一些特殊的保证,以便这种事情是安全的。
重要的规则是,如果联合中的两个POD结构以相同的成员类型开头,则允许您使用共享成员的“公共初始序列”。因此,如果设置了key.type
,那么阅读button.type
是合法的,它将具有相同的值。
此外,直接在union中的普通数据成员(基本类型)type
必须在内存中布局,就好像它只在struct
中包含该成员一样。换句话说,type
也相当于key.type
和button.type
等。