当前位置: 首页 > news >正文

C++派生数据类型与类型转换全解析(结构体、类、枚举、联合体对比+完整示例)

目录

一、C++ 数据类型体系概览

二、常见派生数据类型及示例

三、结构体 vs 类 vs 联合体 vs 枚举

✅ 示例 1:结构体 struct

✅ 示例 2:类 class

✅ 示例 3:联合体 union

✅ 示例 4:枚举 enum

四、类型别名:typedef 与 using

五、标准库常用类型总结

六、四种类型转换总结

示例 1:static_cast

示例 2:dynamic_cast

示例 3:const_cast

示例 4:reinterpret_cast

七、总结对比表

八、结语


一、C++ 数据类型体系概览

在 C++ 中,数据类型可以分为三大类:

类型类别说明举例
基本数据类型由语言内置的原生类型int, float, double, char, bool
派生数据类型基于基本类型组合或封装而成数组、指针、引用、函数、结构体、类、联合体、枚举
抽象/用户定义类型用户通过 classstructenumunion 等方式自定义MyClass, Point, Color

二、常见派生数据类型及示例

数据类型描述示例
数组一组相同类型元素的集合int arr[5] = {1, 2, 3, 4, 5};
指针存储变量内存地址int* ptr = &x;
引用变量的别名(必须初始化)int& ref = x;
函数封装一段逻辑运算int func(int a, int b);
结构体 struct聚合不同类型成员(默认公有)struct Point {int x; int y;};
类 class支持封装、继承、多态(默认私有)class MyClass {private: int data; };
联合体 union多成员共享一段内存union Data {int i; float f;};
枚举 enum一组具名整型常量集合enum Color {RED, GREEN, BLUE};

三、结构体 vs 类 vs 联合体 vs 枚举

特性结构体(struct)类(class)联合体(union)枚举(enum)
定义方式struct 名 {成员;};class 名 {成员;};union 名 {成员;};enum 名 {常量列表};
默认访问权限publicprivatepublicpublic
内存分配每个成员独占内存每个成员独占内存所有成员共享同一块内存每个枚举常量为整型值
用途聚合不同类型数据面向对象封装与继承存储互斥数据定义常量集合
支持函数✅ 可以包含函数✅ 成员函数、构造、析构❌ 不支持成员函数❌ 不支持成员函数
封装性
示例场景点坐标、传感器数据机器人类、控制器类多格式数据表示状态机状态定义

✅ 示例 1:结构体 struct

#include <iostream>
using namespace std;struct Point {int x;int y;void print() {cout << "Point(" << x << ", " << y << ")" << endl;}
};int main() {Point p1 = {3, 4};p1.print();return 0;
}

输出:

Point(3, 4)

✅ 示例 2:类 class

#include <iostream>
using namespace std;class Rectangle {
private:int width, height;
public:Rectangle(int w, int h) : width(w), height(h) {}int area() { return width * height; }
};int main() {Rectangle rect(5, 6);cout << "Area = " << rect.area() << endl;return 0;
}

输出:

Area = 30

🔍 区别:struct 默认成员是 public,class 默认是 private。除此之外几乎完全等价。


✅ 示例 3:联合体 union

#include <iostream>
using namespace std;union Data {int i;float f;char c;
};int main() {Data data;data.i = 10;cout << "i = " << data.i << endl;data.f = 3.14;cout << "f = " << data.f << endl;cout << "i (after f assigned) = " << data.i << endl; // 同块内存被覆盖return 0;
}

输出(内存被覆盖):

i = 10
f = 3.14
i (after f assigned) = 1078523331

⚠️ union 共享同一段内存,只能使用其中一个成员,典型应用是节省空间(如协议帧解析、字节重解释)。


✅ 示例 4:枚举 enum

#include <iostream>
using namespace std;enum Color { RED, GREEN = 5, BLUE };int main() {Color c = BLUE;cout << "RED = " << RED << ", GREEN = " << GREEN << ", BLUE = " << BLUE << endl;cout << "c = " << c << endl;return 0;
}

输出:

RED = 0, GREEN = 5, BLUE = 6
c = 6

🎨 枚举让代码更可读,不必再用“魔法数字”。


四、类型别名:typedef 与 using

C++ 提供两种定义别名的方式:

关键字语法示例备注
typedeftypedef 原类型 新名;typedef int MyInt;C 时代传统写法
usingusing 新名 = 原类型;using MyInt = int;C++11 推荐写法

示例:

typedef unsigned long ulong_t;
using ushort_t = unsigned short;ulong_t a = 100;
ushort_t b = 200;

五、标准库常用类型总结

类型功能示例
std::string字符串类型std::string s = "Hello";
std::vector动态数组std::vector<int> v = {1, 2, 3};
std::array固定大小数组(C++11)std::array<int,3> a = {1,2,3};
std::pair存储两个值的键值对std::pair<int, string> p(1, "A");
std::map键值映射容器std::map<int, string> m;
std::set唯一值集合std::set<int> s = {1,2,3};

六、四种类型转换总结

cast作用何时用失败时表现风险级别

static_

cast

编译期能判定的常规转换(数值、指针上下行的受限情况、显式构造、void*↔T* 等)不需要运行期检查、转换语义明确时编译不过
dynamic_cast运行期带 RTTI 的安全向下转型/交叉转型(必须多态:基类里有虚函数)基类指针/引用要转回真实派生类型时指针版返回 nullptr;引用版抛 std::bad_cast低~中

const_

cast

增/删顶层 const/volatile 限定接口不匹配(如第三方 API 少了 const)且底层对象本身可改——中(误用=UB)
reinterpret_cast重新解释位模式(原类型与目标类型无语义关系)极少用;底层/硬件/序列化场景,且你能掌控 ABI/对齐/别名规则——高(极易 UB)

static(静态可判定)、dynamic(运行期检查)、const(只改限定符)、reinterpret(重新解释位)。


示例 1:static_cast

int i = 42;
float f = static_cast<float>(i);

解释把 int 转 float,这是标准的算术类型提升static_cast 完全胜任且最清晰
特点

  • 编译期就能确定可行,失败会直接报错。

  • 对于窄化(如 double → int)仍然允许,但可能丢精度——“可编译≠无信息损失”。

  • 比 C 风格 (float)i 更“窄”,不会悄悄做 const 去除或 reinterpret 之类的危险事。

实战建议

  • 所有“正常的数值类型转换”都首选 static_cast

  • 有窄化可能时,最好自己加注释或显式检查范围。


示例 2:dynamic_cast

class Base { public: virtual ~Base() {} };
class Derived : public Base { public: void show(){ cout<<"Derived\n"; } };Base* b = new Derived();
Derived* d = dynamic_cast<Derived*>(b);
if (d) d->show(); // 输出 Derived

解释

  • 基类里定义了虚析构函数Base 成为多态类型

  • b 实际指向 Derived,所以 dynamic_cast<Derived*>(b) 成功,返回非空指针。

  • 如果真实对象不是 Derived,指针版 dynamic_cast 会返回 nullptr;引用版会抛 std::bad_cast

何时用

  • 你“手里只有基类指针/引用”,需要在运行期确认真实类型并向下转回派生类。

  • 类层次复杂(菱形、多重继承)或需要交叉转型(同一最底层对象的另一个基类视图)。

对比 static_cast

  • static_cast<Derived*>(Base*) 不会做运行期检查,错了就是 UB。

  • 能用 dynamic_cast 的下行转型,除非你 100% 能证明类型关系,否则优先 dynamic_cast


示例 3:const_cast

const int ci = 10;
int& ri = const_cast<int&>(ci);
ri = 20;
std::cout << ri; // 输出 20(表面上),但这是未定义行为(UB)

关键点

  • 你把一个真正的常量对象 ciconst 去掉后写入了它。

  • 标准明确规定:如果原对象是 const,通过去除 const 后写入属于未定义行为(UB)

    • UB 的表现可能是看起来“成功了”、也可能崩溃、也可能被编译器优化掉,不可依赖

正确用法(只在原对象本身是非常量时移除 const):

void takes_int_ref(int&);        // 第三方旧接口,不带 const
void takes_int_cref(const int&); // 新接口,带 constvoid demo() {int x = 10;                  // 注意:x 是非 constconst int& cx = x;           // 顶层 const 的“视图”// 正确:底层对象可写,只是我们手里拿的是 const 视图takes_int_ref(const_cast<int&>(cx));
}

实战建议

  • const_cast 只用于API 适配(对方函数签名不合理),且你能确认底层对象是可修改的

  • 永远不要对真正的常量(如 const int ci;static const、放在只读段的对象)做写入。


示例 4:reinterpret_cast

const int ci = 10;
int& ri = const_cast<int&>(ci);
ri = 20;
std::cout << ri; // 输出 20(表面上),但这是未定义行为(UB)

问题很大

  1. 严格别名规则(strict aliasing):通过不相关类型(intfloat)的引用别名同一内存属于 UB。

  2. 对齐/大小:若类型对齐不同或大小不同,也可能 UB。

  3. 可移植性:假设了目标机器 intfloat 尺寸/编码与你的常量匹配(未必成立)。

更安全的现代写法(C++20 起)std::bit_cast

#include <bit>
#include <cstdint>uint32_t u = 0x40490fdbu;     // 明确位宽
float f = std::bit_cast<float>(u);  // 位级无 UB 的拷贝
std::cout << f << '\n';

实战建议

  • reinterpret_cast 几乎只在你完全确定 ABI/内存布局的底层场景才用;一般业务/库代码避免。

  • 只想“把指针当字节地址打印/存储”?用 std::uintptr_t 做中转;只想按位搬运?用 bit_cast/memcpy


七、总结对比表

类型是否支持函数内存共享是否面向对象默认权限典型用途
structpublic聚合数据
classprivate封装/继承/多态
unionpublic节省空间
enumpublic常量集合

八、结语

💬 一句话总结:

  • struct:数据打包;

  • class:对象封装;

  • union:内存共用;

  • enum:枚举常量;

  • typedef / using:起别名方便代码阅读;

  • static_cast / dynamic_cast / const_cast / reinterpret_cast:类型转换的四种武器。

http://www.dtcms.com/a/586429.html

相关文章:

  • 基于 GEE 的 MODIS 数据逐月植被覆盖度(FVC)计算与数据导出完整流程
  • 做网站运营用什么软件李杰老师网站建设
  • 网站文章怎么做内链网页设计作品集模板
  • MPU6050驱动配置
  • linux软件安装与管理
  • 7.基础--SQL--DDL-数据类型及案例
  • 网站内部seo优化包括wordpress主题详情更改版权
  • 网站积分系统方案网络服务商网站
  • 浏览器如何做购物网站为什么网站的备案号在备案网站查询不到
  • COT控制架构下ASP3605负载调整特性评估
  • Java118 反射
  • Optuna超参数调优图例解读之Optimization History Plot(优化历史图)
  • 【Python】Tuple (元组)
  • 小吃培训网站源码广电网络公司优秀营销案例
  • 企业电子商务网站建设设计目的暴雪游戏有哪些
  • 仓颉初使用,资料查找及换进安装使用指导
  • 事务的相关介绍
  • 安徽省工程建设信息网站投资公司设立条件
  • Spring 框架核心技术全解析
  • C# OpenCVSharp使用 读光-票证检测矫正模型
  • 更换空间对网站的影响开发app需要什么设备
  • 佛山网站制作公司沈阳网页设计招聘
  • 南宁比优建站wordpress管理工具栏
  • 企业如何建设自己的网站网站主页跳转index
  • 网站利用百度离线地图淘宝电脑版网页
  • 工业控制网关物联网解决方案软硬件定制:我是你的研发部
  • 第2章 传感器技术与数据处理
  • 【开题答辩全过程】以 房地产销售管理系统为例,包含答辩的问题和答案
  • 建设项目环评验收网站建设行业门户网站需要什么条件
  • maven常用的命令