联合体union在立体几何中的妙用

来源:互联网 发布:大智慧软件售后 编辑:程序博客网 时间:2024/05/03 13:22

联合体union在立体几何中的妙用

为了更好地理解三维游戏编程,我开始研究了立体几何,注意,是立体解析几何,里面涉及到了很多元组、向量和矩阵的知识。虽然还有一些不懂,可是这唤醒了我在高等数学中学到的知识,我想以后还是有很大的用处的。

当然,数学是工具,是为我们编程服务的。但是出于对性能和简洁性的敏感,在构建数学库的过程中我千方百计减少我们的代码量。在我所学的封装、继承和多态以及模板中进行选择,其中一个鲜有接触的关键字union映入了我的眼帘。

union,即联合体,主要是为了解决相同的内容用不同的符号访问的问题。在union的内部,多个成员共享相同的内存,有利于实现该联合体用途的多样性。此外联合体可以用来判断大端和小端的问题:

#include <iostream>union Test{    int i;    char a;};int main( int, char** ){    using namespace std;    cout << "本程序用来判断是否是大端(Big Endian)还是小端(Small Endian)。\n" << '\n';    Test aTest;    aTest.i = 1;    if ( aTest.a == 1 )        cout << "此计算机是小端。\n";    else cout << "此计算机是大端。\n";    return 0;}

在这个例子中,如果是小端,那么1放在低字节,这样charainti都可以访问到,否则charainti访问的是不同的内容。则为大端。

在构建我的3D数学库的时候,我曾经考虑,使用一个通用的类模板Tuple表示元组,通过模板参数234将其实例化为不同维数的元组。可是除了三维坐标,其它的比如说Size、和Color都可以用元组来表示,那么有什么办法可以让我们少写代码呢?在看了union的用法后,我想到何不使用union来完成这个任务?

// 以下代码需要高级版本C++编译器支持template <typename T, int n>union Tuple{    T m[n];};// 特化template <typename T>union Tuple<T, 2>{    Tuple( void ){ }    Tuple( T _1, T _2 )    {        Set( _1, _2 );    }    void Set( T _1, T _2 )    {        m[0] = _1, m[1] = _2;    }    operator T*( void ) // 重载类型转换函数    {        return m;    }    Tuple operator+( const Tuple& obj ) const// 重载减号    {        Tuple ret;        ret.m[0] = m[0] + obj.m[0];        ret.m[1] = m[1] + obj.m[1];        return ret;    }    Tuple operator-( const Tuple& obj ) const// 重载减号    {        Tuple ret;        ret.m[0] = m[0] - obj.m[0];        ret.m[1] = m[1] - obj.m[1];        return ret;    }    Tuple& operator+=( const Tuple& obj )    {        m[0] += obj.m[0];        m[1] += obj.m[1];        return *this;    }    //-------------------------------------    T m[2];    struct    {        T x, y;    };    struct    {        T w, h;    };};template <typename T>union Tuple<T, 3>{    Tuple( void ){ }    Tuple( T _1, T _2, T _3 )    {        Set( _1, _2, _3 );    }    void Set( T _1, T _2, T _3 )    {        m[0] = _1, m[1] = _2, m[2] = _3;    }    operator T*( void ) // 重载类型转换函数    {        return m;    }    Tuple operator+( const Tuple& obj ) const// 重载减号    {        Tuple ret;        ret.m[0] = m[0] + obj.m[0];        ret.m[1] = m[1] + obj.m[1];        ret.m[2] = m[2] + obj.m[2];        return ret;    }    Tuple operator-( const Tuple& obj ) const// 重载减号    {        Tuple ret;        ret.m[0] = m[0] - obj.m[0];        ret.m[1] = m[1] - obj.m[1];        ret.m[2] = m[2] - obj.m[2];        return ret;    }    Tuple operator*( const T& obj )     const// 重载减号    {        Tuple ret;        ret.m[0] = m[0] * obj;        ret.m[1] = m[1] * obj;        ret.m[2] = m[2] * obj;        return ret;    }    Tuple operator-( void )    {        return Tuple( -m[0], -m[1], -m[2] );    }    Tuple& operator+=( const Tuple& obj )    {        m[0] += obj.m[0];        m[1] += obj.m[1];        m[2] += obj.m[2];        return *this;    }    //-------------------------------------    T m[3];    struct    {        T x, y, z;    };    struct    {        T r, g, b;    };};template <typename T>union Tuple<T, 4>{    Tuple( void ){ }    Tuple( T _1, T _2, T _3, T _4 )    {        Set( _1, _2, _3, _4 );    }    void Set( T _1, T _2, T _3, T _4 )    {        m[0] = _1, m[1] = _2, m[2] = _3, m[3] = _4;    }    operator T*( void ) // 重载类型转换函数    {        return m;    }    Tuple operator+( const Tuple& obj ) const// 重载减号    {        Tuple ret;        ret.m[0] = m[0] + obj.m[0];        ret.m[1] = m[1] + obj.m[1];        ret.m[2] = m[2] + obj.m[2];        ret.m[3] = m[3] + obj.m[3];        return ret;    }    Tuple operator-( const Tuple& obj ) const// 重载减号    {        Tuple ret;        ret.m[0] = m[0] - obj.m[0];        ret.m[1] = m[1] - obj.m[1];        ret.m[2] = m[2] - obj.m[2];        ret.m[3] = m[3] - obj.m[3];        return ret;    }    Tuple& operator+=( const Tuple& obj )    {        m[0] += obj.m[0];        m[1] += obj.m[1];        m[2] += obj.m[2];        m[3] += obj.m[3];        return *this;    }    //-------------------------------------    T m[4];    struct    {        T x, y, z, w;    };    struct    {        T r, g, b, a;    };};// 定义数据类型typedef Tuple<float, 2> Vector2F, Point2F, Size2F;typedef Tuple<float, 3> Vector3F, Color3F, Point3F;typedef Tuple<float, 4> Vector4F, Color4F;

在上面的代码中,我尝试了将联合体和模板相结合,使用了模板偏特化的技术。此外还在union中嵌入了无名的结构体。比如Tuple<float,3>,我既可以访问Tuple<float,3>::xTuple<float,3>::yTuple<float,3>::z,也可以访问Tuple<float,3>::rTuple<float,3>::gTuple<float,3>::b。所以用typedef定义向量和颜色,成员可以完全不同,但是它们所指向的内容是相同的。

上述代码可以很顺利地通过,如果你使用的是微软的VC6.0编译器,那么无法支持模板偏特化的特性。此外,一些IDE的自动补全功能在推测联合体模板的成员时候会失效。比如我的QtCreator2.6就无法正确地推测成员。

原创粉丝点击