C++ 编程/联合体
联合体关键字用于定义联合体类型。
- 语法
union union-name
{
public-members-list;
private:
private-members-list;
} object-list;
联合体类似于struct
(比class
更像),联合体在union
的字段共享内存中的相同位置,并且默认情况下是public
而不是private
方面有所不同。union
的大小是其最大字段的大小(如果对齐要求这样做,则更大,例如在 SPARC 机器上,一个union
包含一个double
和一个char [17]
,因此其大小可能是 24,因为它需要 64 位对齐)。联合体不能有析构函数
。
这样做有什么意义呢?联合体提供多种方法来查看同一个内存位置,从而允许更有效地使用内存。C++ 中大多数联合体的使用都被面向对象的功能所涵盖,因此它在 C 中更为常见。但是,有时在性能至关重要或知道所讨论的项目不会被扩展时,避免面向对象编程的繁文缛节是方便的。
union Data {
int i;
char c;
};
联合体对于涉及写入同一个内存区域但位于分配内存空间的不同部分的低级编程任务非常有用,例如
union item
{
// The item is 16-bits
short theItem;
// In little-endian lo accesses the low 8-bits -
// hi, the upper 8-bits
struct { char lo; char hi; } portions;
};
item tItem;
tItem.theItem = 0xBEAD;
tItem.portions.lo = 0xEF; // The item now equals 0xBEEF
使用此联合体,我们可以修改 theItem 的低位字节或高位字节,而不会影响任何其他字节。
联合体的现实例子是 SDL 的事件系统,SDL 是 C 中的图形库。在图形编程中,事件是由用户触发的操作,例如鼠标移动或键盘按下。SDL 的职责之一是处理事件并提供一种机制供程序员监听和响应事件。
// primary event structure in 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;
除了Uint8(一个 8 位无符号
整数)之外,每种类型都是一个包含该特定事件详细信息的结构体。
// SDL_MouseButtonEvent
typedef struct
{
Uint8 type;
Uint8 button;
Uint8 state;
Uint16 x, y;
} SDL_MouseButtonEvent;
当程序员从 SDL 接收事件时,他首先检查类型值。这告诉他事件是什么类型。根据此值,他要么忽略该事件,要么通过获取联合体的相应部分来获取更多信息。
例如,如果程序员在SDL_Event ev中接收到事件,他可以使用以下代码对鼠标点击做出反应。
if (ev.type == SDL_MOUSEBUTTONUP && ev.button.button == SDL_BUTTON_RIGHT)
{
cout << "You have right-clicked at coordinates (" << ev.button.x << ", "
<< ev.button.y << ")." << endl;
}
虽然可以用结构体而不是联合体来提供相同的功能,但联合体更节省空间;结构体将为每种不同的事件类型使用内存,而联合体只为一种事件类型使用内存。由于每个实例只有一个条目有意义,因此在这种情况下使用联合体是合理的。
此方案也可以使用面向对象的 C++ 的多态性和继承功能构建,但是设置将很复杂,效率低于此方案。使用联合体会失去类型安全性,但会提高性能。
this 关键字是一个隐式创建的指针,它只能在联合体(或结构体或类)的非静态成员函数中访问,并且指向调用成员函数的对象。this 指针在静态成员函数中不可用。这将在介绍联合体时再次说明,在更深入的分析中,将在关于类的部分中提供。