C++ - 关于包含"类型"成员的联合的问题

Rus*_*sel 7 c c++ unions

关于工会我还有一些不明白的问题.我已经阅读了很多他们的用途,并且在大多数情况下可以看到它们如何有用并理解它们.我已经看到他们可以提供原始的"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;
Run Code Online (Sandbox Code Playgroud)

我无法理解的是,如何在那里与活动类型共存的"类型"成员?这些是不是每个只允许一次存在一个,因为它们占据相同的记忆区域?工会不会随时存在,不论是一种类型还是其中一种事件?

我知道每个事件实际上都是一个带有类型成员的结构,例如:

// SDL_MouseButtonEvent

typedef struct{
     Uint8 type;
     Uint8 button;
     Uint8 state;
     Uint16 x, y;
} SDL_MouseButtonEvent;
Run Code Online (Sandbox Code Playgroud)

这怎么有意义?这是否以某种方式允许联合的类型成员表示联合当前的任何结构的类型?当一个联盟的每个成员除了一个结构并且每个结构包含那个成员时,会发生这种奇怪的效果吗?

你可以在不知道对象是哪个结构的情况下访问struct成员吗?

谢谢!

Jam*_*lis 9

如果每个事件类型都有一个Uint8作为其第一个数据成员,那么该type成员union只是一个方便.

联合的一般规则是,您只能使用您编写的最后一个数据成员访问联合中的数据.所以,如果你上次写信给active你,你就不能再读一读了key.

此规则的一个例外是,如果联合的多个成员共享相同的前缀(如果它们的第一个数据成员相同),则可以通过共享前缀的联合的任何数据成员访问该前缀.所以,在这里,你可以引用active.type或者key.type,无论联盟的哪个数据成员是活动的,它都可以工作.

type成员SDL_Event只是一个方便的快捷方式,允许您访问该type字段而无需将其限定为event_object.active.typeevent_object.key.type.你可以使用event_object.type.

  • 我仍然发现这个结构不寻常,我之前看到过:`struct SDLEvent {Uint8 type; union {type1 t1; type2 t2 ...}};` (2认同)

Ano*_*on. 6

让我们来看看联盟是如何在记忆中铺设的:

Address:    Uint8    MouseButtonEvent   KeyboardEvent
x+0x0       type     type               type
x+0x1       -        button             ?
x+0x2       -        state              ?
...
Run Code Online (Sandbox Code Playgroud)

事实恰恰相反,type成员都排成一行,所以无论它是什么类型,访问联合Uint8将产生事件的实际类型.