ISO C++14及以后版本如何为数据定义多变量名?解决编译错误C2280
在C++14及以后版本中实现同一数据的多别名(解决C2280错误)
错误原因分析
你的代码编译报错C2280,核心问题有三个:
- 匿名结构体嵌套union是编译器扩展:这种写法是GCC、VC等编译器的非标准特性,在标准C++14及以后版本中属于未定义行为,跨版本编译必然出问题。
- 引用成员导致默认函数被删除:类中包含
Type&类型的成员,编译器会自动删除默认的拷贝赋值运算符(operator=),一旦代码中出现对象赋值操作,就会触发“尝试引用已删除函数”的错误。 - union成员初始化违反语义:union同一时刻只能有一个活跃成员,你在构造函数中同时初始化
m_x、m_s、m_r等多个union成员,完全违反了标准C++对union的定义。
标准兼容的实现方案
放弃非标准的union写法,改用两种标准C++方式实现多别名需求:
方案1:成员函数返回引用(无额外内存开销)
这是最推荐的方式,完全符合标准,且类型安全:
/// 四分量向量引用 template <typename Type> class CVectorReference4 { private: Type& m_v0; Type& m_v1; Type& m_v2; Type& m_v3; public: // 空间坐标别名(支持const/非const对象) Type& x() { return m_v0; } const Type& x() const { return m_v0; } Type& y() { return m_v1; } const Type& y() const { return m_v1; } Type& z() { return m_v2; } const Type& z() const { return m_v2; } Type& w() { return m_v3; } const Type& w() const { return m_v3; } // 材质坐标别名 Type& s() { return m_v0; } const Type& s() const { return m_v0; } Type& t() { return m_v1; } const Type& t() const { return m_v1; } Type& p() { return m_v2; } const Type& p() const { return m_v2; } Type& q() { return m_v3; } const Type& q() const { return m_v3; } // 颜色坐标别名 Type& r() { return m_v0; } const Type& r() const { return m_v0; } Type& g() { return m_v1; } const Type& g() const { return m_v1; } Type& b() { return m_v2; } const Type& b() const { return m_v2; } Type& a() { return m_v3; } const Type& a() const { return m_v3; } // 构造函数 CVectorReference4(Type& Value0, Type& Value1, Type& Value2, Type& Value3) : m_v0(Value0), m_v1(Value1), m_v2(Value2), m_v3(Value3) {} CVectorReference4(Type* Array) : m_v0(Array[0]), m_v1(Array[1]), m_v2(Array[2]), m_v3(Array[3]) {} // 析构函数(无需多态可去掉virtual,减少开销) virtual ~CVectorReference4() = default; // 拷贝构造函数(引用成员必须显式定义) CVectorReference4(const CVectorReference4<Type>& other) : m_v0(other.m_v0), m_v1(other.m_v1), m_v2(other.m_v2), m_v3(other.m_v3) {} // 显式定义拷贝赋值运算符(解决C2280错误) CVectorReference4& operator=(const CVectorReference4<Type>& other) { // 引用无法重新绑定,此处赋值的是引用指向的对象 m_v0 = other.m_v0; m_v1 = other.m_v1; m_v2 = other.m_v2; m_v3 = other.m_v3; return *this; } };
方案2:成员变量别名(保留.访问语法)
如果需要保留原代码中vec.x的访问方式,可使用C++11及以后支持的成员变量别名:
/// 四分量向量引用 template <typename Type> class CVectorReference4 { private: Type& m_v0; Type& m_v1; Type& m_v2; Type& m_v3; public: // 空间坐标别名 Type& x = m_v0; Type& y = m_v1; Type& z = m_v2; Type& w = m_v3; // 材质坐标别名 Type& s = m_v0; Type& t = m_v1; Type& p = m_v2; Type& q = m_v3; // 颜色坐标别名 Type& r = m_v0; Type& g = m_v1; Type& b = m_v2; Type& a = m_v3; // 构造函数、析构函数、拷贝构造/赋值同方案1 CVectorReference4(Type& Value0, Type& Value1, Type& Value2, Type& Value3) : m_v0(Value0), m_v1(Value1), m_v2(Value2), m_v3(Value3) {} CVectorReference4(Type* Array) : m_v0(Array[0]), m_v1(Array[1]), m_v2(Array[2]), m_v3(Array[3]) {} virtual ~CVectorReference4() = default; CVectorReference4(const CVectorReference4<Type>& other) : m_v0(other.m_v0), m_v1(other.m_v1), m_v2(other.m_v2), m_v3(other.m_v3) {} CVectorReference4& operator=(const CVectorReference4<Type>& other) { m_v0 = other.m_v0; m_v1 = other.m_v1; m_v2 = other.m_v2; m_v3 = other.m_v3; return *this; } };
注意:这种方式每个别名会占用一个指针大小的内存,而成员函数方式不会增加类的体积。
内容的提问来源于stack exchange,提问作者CROMA
相关产品推荐
相关产品推荐

