C 语言 union 可存儲 struct(無構造函數)。C++ 繼承此規則:
帶有用戶聲明構造函數、析構函數、拷貝操作、非平凡默認構造的類,不能作為 union 成員。
否則編譯錯誤:error C2621: 'TestUnion' : union member has copy constructor。
去掉構造函數即可編譯,但喪失 C++ 初始化特性,無實際意義。
替代方案:存儲對象指針,間接引用多態對象。
嘗試在構造函數初始化列表直接初始化匿名 union 成員:
class TestUnion {
union { const char* ch_; long l_; } data_; // 匿名 union
TestUnion(const char* ch) : data_.ch_(ch) {} // 錯誤:匿名 union 無構造函數
TestUnion(long l) : data_.l_(l) {}
};
原因:匿名 union 成員無構造函數,編譯器不知如何初始化。
修復:為 union 命名並顯式聲明構造函數:
class TestUnion {
union DataUnion {
DataUnion(const char* ch) : ch_(ch) {}
DataUnion(long l) : l_(l) {}
const char* ch_;
long l_;
} data_;
TestUnion(const char* ch) : data_(ch) {} // 初始化整個 union
TestUnion(long l) : data_(l) {}
};
現在編譯通過,且保留類型安全初始化。
std::variant (C++17) 或 boost::variant,類型安全、支持非 POD、訪問器模式優雅處理多態數據。