有些類別的實例,可能包含不同型態的成員,然而,在某個時間點上,只會有一個成員是有效的,例如,你可能會設計一個磁頭類別,磁頭讀取磁帶中的資料並儲存為對應的資料型態:
#include <iostream>
using namespace std;
class Output {
public:
virtual void write(char cvalue) = 0;
virtual void write(int ivalue) = 0;
virtual void write(double dvalue) = 0;
virtual ~Output() = default;
};
class Console : public Output {
public:
void write(char cvalue) override {
cout << cvalue << endl;
}
void write(int ivalue) override {
cout << ivalue << endl;
}
void write(double dvalue) override {
cout << dvalue << endl;
}
};
class Head {
char cvalue;
int ivalue;
double dvalue;
enum {CHAR, INT, DOUBLE} type;
public:
void read(char cvalue) {
this->cvalue = cvalue;
this->type = CHAR;
}
void read(int ivalue) {
this->ivalue = ivalue;
this->type = INT;
}
void read(double dvalue) {
this->dvalue = dvalue;
this->type = DOUBLE;
}
void writeTo(Output &output) {
switch(this->type) {
case CHAR:
output.write(this->cvalue);
break;
case INT:
output.write(this->ivalue);
break;
case DOUBLE:
output.write(this->dvalue);
break;
}
}
};
int main() {
Console console;
Head head;
head.read(10);
head.writeTo(console);
head.read('A');
head.writeTo(console);
return 0;
}
在上例中,Head
一次只儲存一種資料,並依 type
決定該寫出哪種資料,因為 Head
一次只儲存一種資料,不需要分別為 cvalue
、ivalue
、dvalue
各開一個記憶體空間。
你可以使用 union
,它是一種特殊的類別,維護足夠的空間來置放多個資料成員中的一種,而不是為每個資料成員配置各自空間,例如:
...略
class Head {
union {
char cvalue;
int ivalue;
double dvalue;
} value;
enum {CHAR, INT, DOUBLE} type;
public:
void read(char cvalue) {
this->value.cvalue = cvalue;
this->type = CHAR;
}
void read(int ivalue) {
this->value.ivalue = ivalue;
this->type = INT;
}
void read(double dvalue) {
this->value.dvalue = dvalue;
this->type = DOUBLE;
}
void writeTo(Output &output) {
switch(this->type) {
case CHAR:
output.write(this->value.cvalue);
break;
case INT:
output.write(this->value.ivalue);
break;
case DOUBLE:
output.write(this->value.dvalue);
break;
}
}
};
...略
在 Head
中定義了匿名的 union
並建立了 value
成員,union
配置足夠大的空間以來容納最大長度的資料成員,以上例而言,最大長度是 double
型態,因此 value
成員的大小是 double
的長度,由於 union
的資料成員共用記憶體空間,存取當前具有合法值的資料成員,才能正確地取資料,
union
是種特殊的類別,因此多數的類別語法也可以用於 union
,例如,可以為 union
定義名稱,預設權限為 public
,也可以宣告為 protected
或 private
,可以定義建構函式、解構函式與成員函式等,然而不能擁有虛擬函式,不能繼承其他類別,也不能作為基礎類別。
在 C++ 11 以後,成員的型態可以是自訂型態,可以有建構函式、解構函式或是複製指定運算子,不過並不建議,因為會令管理成員資源更為複雜。