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

2023-11-14

<style type="text/css"> <!-- @page {margin:2cm} pre {font-family:"DejaVu Sans Mono",monospace} p.我的格式-western {font-family:"DejaVu Sans",sans-serif; font-size:10pt} p.我的格式-cjk {font-size:10pt} p.我的格式-ctl {font-size:12pt} p {margin-bottom:0.21cm} --> </style>

联合体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就无法正确地推测成员。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

联合体union在立体几何中的妙用 的相关文章

  • Qt5实现与单片机ATS89S51通信

    Qt实现与单片机直接的通信上位机 单片机代码 测试环境 项目目标 实现效果 关键通信类 QSerialport 总结 这是我大二下学期的单片机课设做的一个小项目 实现上位机与下位机之间的通信 测试环境 开发环境 Qt5 96 Mingw32
  • 【C/C++】报错问题积累

    1 出现Deprecated declaration XXX give arg types c文件中 有没有参数的函数时 声明需要加void即 main c void fun main h void fun void
  • C++知识积累:内存对齐理解

    为什么要进行内存对齐 这是因为CPU的读取总是对齐的 举个例子 假设CPU是32位的 那么CPU每次读取的4字节数据的首地址都是4的倍数 也就是说 内存中数据首地址为4的倍数时 CPU一次操作就可以完成数据读取 假设有一个int型四字节大小
  • JNA模拟复杂的C类型——Java映射char*、int*、float*、double*

    文章目录 引言 Java Native Type Conversions Java和C基本类型指针对应关系 Pointer的具体用法 引言 最近项目在用Java调用C写的一些三方库 没办法直接调 用Java封装一下C的接口 这就少不了要用到
  • c++得到窗口句柄

    include
  • 简析多级指针解引用

    转自 简析多级指针解引用 指针是C语言中公认的最为强大的语法要素 但同时也是最难理解的语法要素 它曾给程序员带来了无数麻烦和痛苦 以致于在C语言之后诞生的很多新兴 语言中我们再也难觅指针的身影了 下面是一个最简单的C语言指针的例子 int
  • C/C++中浮点数格式学习——以IEEE75432位单精度为例

    这是浮点数的通常表示形式 在IEEE754中 单精度浮点数有如下形式 32位单精度 单精度二进制小数 使用32个比特存储 1 8 23位长 S Exp Fraction 31 30至23偏正值 实际的指数大小 127 22至0位编号 从右边
  • 【干货】Chrome插件(扩展)开发全攻略(不点进来看看你肯定后悔)<转>

    干货 Chrome插件 扩展 开发全攻略 不点进来看看你肯定后悔 写在前面 我花了将近一个多月的时间断断续续写下这篇博文 并精心写下完整demo 写博客的辛苦大家懂的 所以转载务必保留出处 本文所有涉及到的大部分代码均在这个demo里面 h
  • LeetCode题目笔记——17.19消失的两个数字

    文章目录 题目描述 题目难度 困难 方法一 暴力 代码 代码优化 方法二 数学方法 代码 总结 题目描述 题目直达 题目难度 困难 方法一 暴力 虽然题目说你能在 O N 时间内只用 O 1 的空间找到它们吗 但是也没有限制我们不能用暴力
  • 模板的完全特例化和部分特例化

    介绍 完全特例化就是类型完全明确的版本 而部分特例化指的是 只知道是几个参数的函数而不知道参数的类型 或者是只知道是引用或者是指针类型 而不知道具体是char 还是 int 模板特例化实例1 template
  • 【C/C++】 - Linux下查找函数头文件 以及 man命令拓展

    背景 比如现在需要找C语言 sleep函数的头文件 使用man来查找 可以先man sleep 可以发现出来的默认是sleep 1 是一个User Commands 明显不是我们需要的 这里提示了 看sleep 3 那我们查看下sleep
  • Open3D(C++)实现建筑物点云立面和平面分割提取

    Open3D C 实现建筑物点云立面和平面分割提取 近年来 点云技术在城市规划 机器人地图构建等领域得到广泛应用 本篇文章将介绍如何利用Open3D C 库实现建筑物点云立面和平面分割提取 准备工作 首先需要编译安装Open3D库 本文使用
  • 检查内存泄露

    自己编写的视频处理程序出现了一个问题 每帧的运行时间随着运行时间在不断增长 很大可能是出现了内存泄露 于是学习了一些查看内存泄露的方法 做了两种尝试 一是VS自带的DEBUG下的检测 view pl html view plain copy
  • 一个简单的参数帮助框架,c实现

    文章目录 具体实现如下 include
  • 虚函数不能声明为static

    虚函数申明为static报错 class Foo public Foo default static virtual Foo int main Foo foo return 0 main cpp 10 25 error member Foo
  • enable_shared_from_this使用介绍

    文章目录 enable shared from this定义 使用场合 源码实现 注意 enable shared from this定义 定义于头文件 template lt class T gt class enable shared
  • 【C++】运算符重载

    加号运算符重载 include
  • C++中的并发多线程网络通讯

    C 中的并发多线程网络通讯 一 引言 C 作为一种高效且功能强大的编程语言 为开发者提供了多种工具来处理多线程和网络通信 多线程编程允许多个任务同时执行 而网络通信则是现代应用程序的基石 本文将深入探讨如何使用C 实现并发多线程网络通信 并
  • C 语言运算符详解

    C 语言中的运算符 运算符用于对变量和值进行操作 在下面的示例中 我们使用 运算符将两个值相加 int myNum 100 50 虽然 运算符通常用于将两个值相加 就像上面的示例一样 它还可以用于将变量和值相加 或者将变量和另一个变量相加
  • C++ 中 const 和 constexpr 关键字解析:常量、函数和指针

    很多 C 的初学者看到 const 这个关键字的第一反应都是一头雾水 主要是因为 const 可 以出现在很多的位置 以及后面加入的 constexpr 更是常常感到困惑 今天就为大家一一解释出现它们的含义和以及作用 const 关键字 c

随机推荐

  • 设计模式:中介模式

    中介模式听名字作为中介 在复杂的调用关系中做个中介传递 类似于在状态机中弄一个中心点 所有的关系状态转移交给中介来处理 同样也是一个重在实用意义 实现结构倒是不要求什么 实际上结构跟观察者比较像 Mediator Design Patter
  • 魔兽世界服务器列表显示不兼容,魔兽世界显示游戏设备驱动不兼容怎么解决_魔兽世界显示游戏设备驱动不兼容解决办法_牛游戏网...

    魔兽世界 显示游戏设备驱动不兼容怎么解决 在客户端更新晋级后登入游戏设备 其显现驱动不兼容 这是因为显卡驱动过期致使 若不挑选更新 亦可经过点击断定按钮越过该提示持续游戏 但每次登录都会呈现 这儿给咱们共享下 魔兽国际 登入显现游戏设备驱动
  • Altium Designer使用-----如果Bill of Materials卡住

    Altium Designer使用 如果Bill of Materials卡住 是没有安装office软件
  • 01背包问题

    01 背包问题 输入 n个商品组成集合O 每个商品有两个属性vi和pi 分别表示体积和价格 背包容量为C 输出 求解一个商品子集包含于O 令价格和最大 容量不超过C 直观上 价格高优先 体积小优先 性价比高优先 都不能得到最优解 解决方案一
  • JDK以及IDEA的安装和配置【JAVA学习--安装配置学习工具】

    目录 一 JDK的安装和环境配置 1 准备工作 2 配置JDK环境变量 3 验证环境配置是否成功 二 安装配置IDEA 创建项目 一 JDK的安装和环境配置 1 准备工作 在Oracal官方网站下载适合自己电脑版本的JDK 并进行安装 注意
  • Linux 查看操作系统

    转载 linux查看操作系统版本信息 这个常用 放在这里备忘 转载上面的链接 一 linux下如何查看已安装的centos版本信息 1 Linux查看当前操作系统版本信息 cat proc version Linux version 2 6
  • Oracle入门笔记(一)——环境配置及简单介绍

    Oracle环境配置及目录结构说明 1 引言 2 Oracle简介 3 Oracle版本迭代说明 4 Oracle的安装与配置 5 Oracle数据库目录介绍 6 Oracle用户说明 7 Oracle启动与关闭 8 参考文献 1 引言 害
  • 负载测试和压力测试的区别

    这两个测试都属于性能测试的一部分 我之前都一直有盲区 每次想起对于这两个概念都不是很清晰 在网上看了一篇文章后 终于有些理解了 特记录下来方便大家理解 这个是网上看到的一篇文章 如果大家还是有些不懂可以在参考一下这篇文章 我所理解的性能测试
  • tp6重定向

    引入 use think exception HttpResponseException 方法 public function redirect args throw new HttpResponseException redirect a
  • 计算机毕业设计-社区疫情防控管理系统springboot-小区疫情管理系统java代码

    计算机毕业设计 社区疫情防控管理系统springboot 小区疫情管理系统java代码 注意 该项目只展示部分功能 如需了解 评论区咨询即可 1 开发环境 开发语言 Java 架构 B S 框架 SpringBoot 前端 HTML CSS
  • Docker-容器

    容器 容器的状态用 docker contaier ls 启动容器 启动一个容器的终端 并允许交互 docker run it ubuntu 16 04 bin bash 当利用 docker run 来创建容器时 Docker 在后台运行
  • uvm message printing mechnism

    原文链接 http www sunburst design com papers CummingsSNUG2014AUS UVM Messages pdf 本文主要介绍了如何控制消息打印的等级 以及禁止消息打印等
  • 使用nginx+uwsgi+flask实现python服务的负载均衡---(2)uwsgi的安装

    0 安装uwsgi 转自官网 使用pip install uwsgi就可以 当然了也可以下载源码自己make 1 配置uwsgi uwsgi 有多种配置可用 1 ini 2 xml 3 json 4 yaml 这里我使用的ini 当然也可以
  • selenium-server-standalone selenium-server 和 selenium-java 的区别

    selenium1 0还是 seleniumRC的时候 需要启动selenium server standalone包 用来做server selenium RC通过server来给code和broswer建立通道 同时 该jar包包括我们
  • BATJ面试必会之Java IO 篇

    一 概览 二 磁盘操作 三 字节操作 实现文件复制 装饰者模式 四 字符操作 编码与解码 String 的编码方式 Reader 与 Writer 实现逐行输出文本文件的内容 五 对象操作 序列化 Serializable transien
  • DDL和DML常用语句总结

    DDL语句 常用来操作数据库 数据库表 用到的语句 create show alter drop 1 操作数据库 CRUD 1 C Create 创建 创建数据库 create database 数据库名称 创建数据库 判断不存在 再创建
  • 前端页面性能优化 - 字体加载优化

    相比于英文的字库来说 中文字库的体积非常之大 小则1M 动辄几十 M 的体积非常常见 所以在前端页面性能优化中 字体加载的优化就显得尤为重要 阅读了相关的知识和文章 在研究了市面上字体加载方案之后 我总结出了目前可行的方案 1 font s
  • 实对称矩阵的特征值求法_机器学习与线性代数 - 特殊矩阵

    在线性代数中 有一些特殊的矩阵具有易于分析和操作的特性 它们的特征向量可能具有特定的特征值或特殊关系 还有一些方法可以将一个矩阵分解成这些 更简单 的矩阵 操作复杂性的降低提高了可伸缩性 然而 即使这些矩阵都是特殊的 它们也不是罕见的 在机
  • linux创建文件软连接和硬链接详解

    前言 linux系统中链接文件仔细区分可以分为软连接 符号链接 和硬链接 软链接比硬链接应用更广泛 所以也可以认为linux链接文件就是指软链接文件 本文将会在第2部分介绍创建软链接和硬链接的基本命令 在第3部分从linux文件系统的角度出
  • 联合体union在立体几何中的妙用

    联合体union在立体几何中的妙用 为了更好地理解三维游戏编程 我开始研究了立体几何 注意 是立体解析几何 里面涉及到了很多元组 向量和矩阵的知识 虽然还有