C++学习:六个月从基础到就业——C++基础语法回顾:结构体与枚举
本文是我C++学习之旅系列的第七篇技术文章,主要回顾C++中的结构体和枚举类型,包括它们的基本概念、语法特性、高级用法以及实际应用场景。查看完整系列目录了解更多内容。
引言
结构体和枚举是C++中用于组织和表示数据的重要工具。结构体允许我们将不同类型的数据组合成一个有意义的整体,而枚举则提供了一种创建命名常量集合的方式。这两种类型不仅是从C语言继承而来的基本特性,在现代C++中也得到了显著的增强和扩展。本文将详细介绍结构体和枚举的概念、语法和使用方法,并探讨它们在实际编程中的应用场景。
结构体基础
什么是结构体
结构体(struct)是一种用户定义的数据类型,它允许我们将不同类型的数据元素(称为成员或字段)组合在一起,形成一个逻辑单位。结构体在表示实体对象(如学生、员工、日期等)时特别有用。
结构体的声明与定义
结构体的基本语法如下:
struct StructName {
// 成员变量
type1 member1;
type2 member2;
// ...
typeN memberN;
// 成员函数(C++特性,C语言的struct没有)
returnType functionName(parameters) {
// 函数体
}
};
示例:定义一个表示学生的结构体
struct Student {
std::string name;
int age;
float gpa;
};
创建结构体变量
定义结构体后,可以创建该类型的变量:
// 声明一个Student类型的变量
Student student1;
// 使用花括号初始化(C++11)
Student student2 = {
"Alice", 20, 3.9};
// 使用点运算符访问和修改成员
student1.name = "Bob";
student1.age = 22;
student1.gpa = 3.7;
// 访问成员
std::cout << "Name: " << student1.name << std::endl;
std::cout << "Age: " << student1.age << std::endl;
std::cout << "GPA: " << student1.gpa << std::endl;
结构体的内存布局
结构体的成员在内存中是连续存储的,每个成员按照声明的顺序分配内存:
struct Example {
char c; // 1字节
int i; // 4字节
double d; // 8字节
};
然而,由于内存对齐的原因,结构体的实际大小可能大于其所有成员大小的总和:
std::cout << "Size of char: " << sizeof(char) << std::endl; // 1
std::cout << "Size of int: " << sizeof(int) << std::endl; // 4
std::cout << "Size of double: " << sizeof(double) << std::endl; // 8
std::cout << "Sum of sizes: " << 1 + 4 + 8 << std::endl; // 13
std::cout << "Size of Example: " << sizeof(Example) << std::endl; // 通常是16(不是13)
这是因为编译器会插入填充字节(padding)以满足对齐要求,提高内存访问效率。
结构体嵌套
结构体可以包含其他结构体作为成员:
struct Date {
int year;
int month;
int day;
};
struct Person {
std::string name;
Date birthdate; // 嵌套结构体
std::string address;
};
// 使用嵌套结构体
Person person;
person.name = "Charlie";
person.birthdate.year = 2000;
person.birthdate.month = 5;
person.birthdate.day = 15;
person.address = "123 Main St";
结构体数组
可以创建结构体类型的数组:
Student classRoom[30]; // 包含30个Student结构体的数组
// 初始化数组元素
classRoom[0] = {
"David", 19, 3.5};
// 使用数组元素
classRoom[1].name = "Emma";
classRoom[1].age = 21;
classRoom[1].gpa = 3.8;
C++中结构体的扩展特性
与C语言不同,C++中的结构体具有面向对象的特性,更接近于类(class)的概念。
结构体中的函数
C++允许在结构体中定义成员函数:
struct Rectangle {
double width;
double height;
// 成员函数
double area() {
return width * height;
}
double perimeter() {
return 2 * (width + height);
}
void scale(double factor) {
width *= factor;
height *= factor;
}
};
Rectangle rect = {
5.0, 3.0};
std::cout << "Area: " << rect.area() << std::endl; // 输出15
std::cout << "Perimeter: " << rect.perimeter() << std::endl; // 输出16
rect.scale(2.0);
std::cout << "New area: " << rect.area() << std::endl; // 输出60
构造函数
C++结构体可以有构造函数,用于初始化结构体变量:
struct Point {
double x;
double y;
// 默认构造函数
Point() : x(0.0), y(0.0) {
}
// 带参数的构造函数
Point(double xVal, double yVal) : x(xVal), y(yVal) {
}
// 计算到原点的距离
double distanceFromOrigin() {
return std::sqrt(x*x + y*y);
}
};
Point p1; // 使用默认构造函数,p1.x = 0, p1.y = 0
Point p2(3.0, 4.0); // 使用带参数的构造函数
std::cout << "Distance: " << p2.distanceFromOrigin() << std::endl; // 输出5
访问限制
C++中的结构体和类一样,可以使用访问说明符(access specifiers)控制成员的可见性:
struct BankAccount {
private: // 私有成员,只能被结构体内的函数访问
double balance;
std::string accountNumber;
public: // 公有成员,可以被任何代码访问
std::string ownerName;
// 构造函数
BankAccount(std::string name, std::string accNum, double initial)
: ownerName(name), accountNumber(accNum), balance(initial) {
}
// 公有方法,提供安全的访问方式
double getBalance() const {
return balance;
}
void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
bool withdraw(double amount) {
if (amount > 0 && balance >= amount) {
balance -= amount;
return true;
}
return false;
}
};
BankAccount account("John Doe", "123456789", 1000.0);
// account.balance = 2000.0; // 错误:balance是私有的
account.deposit(500.0); // 使用公有方法修改余额
std::cout << "Balance: " << account.getBalance() << std::endl; // 输出1500
struct vs class
在C++中,struct和class的唯一区别是默认的访问级别:
- struct中默认的访问级别是public
- class中默认的访问级别是private
除此之外,它们功能完全相同,可以互换使用:
struct StructExample {
// 默认public
int publicByDefault;
private:
int privateExplicit;
};
class ClassExample {
// 默认private
int privateByDefault;
public:
int publicExplicit;
};
使用准则:
- 当主要用于组织数据时,倾向于使用struct
- 当需要封装数据和行为,并强调面向对象设计时,倾向于使用class
结构体的继承
C++中的结构体可以像类一样参与继承:
struct Animal {
std::string name;
int age;
void speak() {
std::cout << "Some generic animal sound" << std::endl;
}
};
struct Dog : Animal {
// Dog继承自Animal
std::string breed;
void speak() {
// 覆盖基类方法
std::cout << "Woof!" << std::endl;
}
void fetch() {
std::cout << name << " is fetching." << std::endl;
}
};
Dog myDog;
myDog.name = "Rex"; // 从Animal继承的成员
myDog.age = 3; // 从Animal继承的成员
myDog.breed = "German Shepherd";
myDog.speak(); // 调用Dog的speak(),输出"Woof!"
myDog.fetch(); // 调用Dog特有的方法
结构体的高级用法
联合体(union)
联合体是一种特殊的结构体,其所有成员共享同一块内存空间。联合体同一时刻只能保存一个成员的值:
union Value {
int intValue;
float floatValue;
char charValue;
};
Value v;
v.intValue = 42;
std::cout << "Int: " << v.intValue << std::endl; // 输出42
v.floatValue = 3.14f;
std::cout << "Float: " << v.floatValue << std::endl; // 输出3.14
// 此时v.intValue的值是未定义的,因为内存被v.floatValue覆盖
std::cout << "Size of Value: " << sizeof(Value) << std::endl; // 输出最大成员的大小,这里是4
联合体常用于节省内存或实现类型转换。
匿名结构体和联合体
C++允许定义匿名的结构体和联合体,它们没有名称,但其成员可以直接访问:
struct Person {
std::string name;
int age;
// 匿名联合体
union {
struct {
// 匿名结构体
int employeeId;
float salary;
}; // 员工信息
struct {
// 匿名结构体
int studentId;
float gpa;
}; // 学生信息
};
};
Person p;
p.name = "Alice";
p.age = 25;
// 作为员工
p.employeeId = 12345;
p.salary = 50000.0f;
// 或者作为学生(注意:覆盖了员工信息)
// p.studentId = 98765;
// p.gpa = 3.9f;
std::cout << p.name << ", " << p.employeeId << std::endl;
匿名结构体/联合体在实现变体类型或节省命名空间时很有用。
位域(Bit Fields)
位域允许以比整型更小的单位分配内存,常用于节省空间或与硬件接口交互:
struct Flags {
unsigned int visible : 1; // 只占1位,可表示0或1
unsigned int enabled : 1; // 只占1位
unsigned int priority : 3; // 占3位,可表示0-7的值
unsigned int : 3; // 未命名位域,占3位(填充)
unsigned int mode : 2; // 占2位,可表示0-3的值
};
Flags f = {
1, 1, 5, 2}; // 初始化位域
std::cout << "Size of Flags: " << sizeof(Flags) << std::endl; // 通常是4(一个unsigned int)
// 修改位域
f.enabled = 0;
f.priority = 7; // 最大值为7(2^3 - 1)
// 访问位域
if (f.visible) {
std::cout << "Flag is visible" << std::endl;
}
位域的限制:
- 不能对位域取地址(&)
- 位域的类型必须是整型或枚举型
- 位域的大小不能超过其类型的大小
结构体对齐与字节对齐
可以使用编译器指令或特性控制结构体的内存对齐:
// 默认对齐
struct DefaultAligned {
char c;
int i;
double d;
};
// 1字节对齐(紧凑布局)
#pragma pack(push, 1)
struct PackedStruct {
char c;
int i;
double d;
};
#pragma pack(pop)
// 使用特性(C++11)
struct alignas(16) AlignedStruct {
char c;
int i;
double d;
};
std::cout << "Size of DefaultAligned: " << sizeof(DefaultAligned) << std::endl; // 通常为16
std::cout << "Size of PackedStruct: " << sizeof(PackedStruct) << std::endl; // 13(紧凑布局)
std::cout << "Size of AlignedStruct: " << sizeof(AlignedStruct) << std::endl; // 32(16字节对齐)
控制对齐对于以下场景很重要:
- 与外部系统或文件格式交互
- SIMD编程和向量化优化
- 缓存优化
使用decltype
和auto
简化结构体
C++11的decltype
和auto
关键字可以简化结构体相关代码:
struct Complex {
double real;
double imag;
Complex operator+(const Complex& other) const {
return {
real + other.real, imag + other.imag};
}
};
Complex c1 = {
1.0, 2.0};
Complex c2 = {
3.0, 4.0};
// 使用auto避免重复类型名
auto sum = c1 + c2;
// 使用decltype获取c1的类型
decltype(c1) another = {
5.0, 6.0};
枚举基础
什么是枚举
枚举(enum)是一种用户定义的数据类型,它由一组命名的常量组成,这些常量被称为枚举器(enumerator)。枚举常用于表示一组相关的常量,如星期几、月份、颜色等。
传统枚举的声明与使用
传统枚举(C风格枚举)的基本语法如下:
enum EnumName {
Value1,
Value2,
// ...
ValueN
};
示例:定义表示星期几的枚举
enum Weekday {
Monday, // 默认值为0
Tuesday, // 1
Wednesday, // 2
Thursday, // 3
Friday, // 4
Saturday, // 5
Sunday // 6
};
Weekday today = Wednesday;
std::cout << "Today is day " << today << std::endl; // 输出2
// 枚举用于条件判断
if (today == Wednesday) {
std::cout << "It's the middle of the week!" << std::endl;
}
// 枚举用于switch语句
switch (today) {
case Monday:
std::cout << "Start of work week." << std::endl;
break;
case Saturday:
case Sunday:
std::cout << "Weekend!" << std::endl;
break;
default:
std::cout << "Midweek." << std::endl;
break;
}
指定枚举值
可以为枚举器指定自定义的值:
enum Status {
OK = 0,
Error = -1,
FileNotFound = 404,
ServerError = 500,
Unknown = 999
};
Status result = FileNotFound;
std::cout << "Status code: " << result << std::endl; // 输出404
// 后续枚举器的值会从前一个递增
enum PrinterState {
Ready = 10, // 10
PaperJam, // 11(自动递增)
OutOfPaper, // 12
OutOfInk = 20, // 20
Offline, // 21
Busy = 21 // 21(可以与前一个值相同)
};
传统枚举的限制
传统枚举有几个重要的限制:
- 名称泄漏:枚举器名称泄漏到包含枚举的作用域
- 类型安全性不强:可以隐式转换为整数,也可以将不同枚举类型进行比较
- 前向声明困难:不能轻易前向声明
示例:
enum Color {
Red, Green, Blue };
enum Traffic {
Stop = 0, Caution = 1, Go = 2 };
// 名称冲突
// enum Direction { Left, Right, Stop }; // 错误:Stop已在作用域中定义
// 类型安全性问题
Color c = Red;
Traffic t = Go;
int i = c; // 合法:枚举可以隐式转换为int
c = Color(3); // 合法,但3不是有效的Color值
if (c == t) {
} // 合法,但比较不同枚举类型没有意义
C++11中的枚举类
C++11引入了枚举类(enum class或scoped enumerations),解决了传统枚举的许多问题。
枚举类的声明与使用
枚举类的基本语法:
enum class EnumName {
Value1,
Value2,
// ...
ValueN
};
示例:
enum class Color {
Red,
Green,
Blue
};
enum class Traffic {
Stop,
Caution,
Go
};
// 使用枚举类
Color c = Color::Red; // 必须使用作用域运算符
Traffic t = Traffic::Go;
// c = Red; // 错误:必须指定作用域
// c = 0; // 错误:没有从int到Color的隐式转换
// int i = c; // 错误:没有从Color到int的隐式转换
// 需要显式转换
int i = static_cast<int>(c); // 正确
std::cout << "Color value: " << i << std::endl; // 输出0
// 不同枚举类的比较
// if (c == t) {} // 错误:不能比较不同的枚举类型
枚举类的优势
- 避免名称冲突:枚举器名称不会泄漏到外部作用域
- 增强类型安全:不能隐式转换为整数或从整数转换
- 不同枚举类不能直接比较:防止无意义的比较
- 可以指定底层类型:控制枚举的大小和表示方式
指定枚举的底层类型
可以为枚举指定底层类型,这对于控制大小或序列化很有用:
// 传统枚举,指定底层类型
enum Status : uint8_t {
OK = 0,
Error = 255
};
// 枚举类,指定底层类型
enum class Direction : int16_t {
North,
East,
South,
West
};
std::cout << "Size of Status: " << sizeof(Status) << std::endl; // 1字节
std::cout << "Size of Direction: " << sizeof(Direction) << std::endl; // 2字节
前向声明枚举
C++11允许前向声明枚举(尤其是枚举类),但需要指定底层类型:
// 前向声明
enum class ApiResult : int; // 必须指定底层类型
// 在头文件中声明
void processResult(ApiResult result);
// 在另一个文件中定义
enum class ApiResult : int {
Success,
InvalidInput,
ConnectionError,
Timeout
};
void processResult(ApiResult result) {
// 实现
}
遍历枚举值
C++不提供内置机制来遍历所有枚举值,但可以创建辅助函数:
enum class Month {
January = 1,
February,
March,
April,
May,
June,
July,
August,
September,
October,
November,
December
};
// 将枚举转换为字符串的帮助函数
std::string monthToString(Month month) {
switch (month) {
case Month::January: return "January";
case Month::February: return "February";
case Month::March: return "March";
case Month::April: return "April";
case Month::May: return "May";
case Month::June: return "June";
case Month::July: return "July";
case Month::August: return "August";
case Month::September: return "September";
case Month::October: return "October";
case Month::November: return "November";
case Month::December: return "December";
default: return "Unknown";
}
}
// 手动遍历
void printAllMonths() {
for (int i = 1; i <= 12; ++i) {
Month m = static_cast<Month>(i);
std::cout << monthToString(m) << std::endl;
}
}
结构体和枚举的实际应用
数据序列化
结构体和枚举在数据序列化中非常有用:
enum class MessageType : uint8_t {
Text = 1,
Image = 2,
Audio = 3,
Video = 4
};
struct Message {
uint32_t id;
MessageType type;
std::string content;
std::time_t timestamp;
// 序列化为二进制
std::vector<uint8_t> serialize() const {
std::vector<uint8_t> data;
// 添加消息ID(4字节)
data.push_back((id >> 24) & 0xFF);
data.push_back((id >> 16) & 0xFF);
data.push_back((id >> 8) & 0xFF);
data.push_back(id & 0xFF);
// 添加类型(1字节)
data.push_back(static_cast<uint8_t>(type));
// 添加内容长度和内容
uint16_t contentLength = content.length();
data.push_back((contentLength >> 8) & 0xFF);
data.push_back(contentLength & 0xFF);
for (char c : content) {
data.push_back(static_cast<uint8_t>(c));
}
// 添加时间戳(8字节)
for (int i = 56; i >= 0; i -= 8) {
data.push_back((timestamp >> i) & 0xFF);
}
return data;
}
// 从二进制反序列化
static Message deserialize(const std::vector<uint8_t>& data) {
Message msg;
// 这里省略实际的反序列化代码,实际应用中需要完整实现
// 并包含边界检查等安全措施
return msg;
}
};
状态机实现
结构体和枚举有助于实现清晰的状态机:
enum class State {
Starting,
Running,
Paused,
Stopping,
Error
};
struct StateMachine {
State currentState;
StateMachine() : currentState(State::Starting) {
}
void transition(State newState) {
switch (currentState) {
case State::Starting:
if (newState == State::Running || newState == State::Error) {
currentState = newState;
} else {
std::cerr << "Invalid transition from Starting state" << std::endl;
}
break;
case State::Running:
if (newState == State::Paused || newState == State::Stopping || newState == State::Error) {
currentState = newState;
} else {
std::cerr << "Invalid transition from Running state" << std::endl;
}
break;
// 其他状态转换逻辑...
default:
std::cerr << "Unknown state" << std::endl;
break;
}
// 执行状态切换后的操作
onStateChange(currentState);
}
void onStateChange(State state) {
std::cout << "State changed to: ";
switch (state) {
case State::Starting: std::cout << "Starting"; break;
case State::Running: std::cout << "Running"; break;
case State::Paused: std::cout << "Paused"; break;
case State::Stopping: std::cout << "Stopping"; break;
case State::Error: std::cout << "Error"; break;
}
std::cout << std::endl;
// 执行特定状态的操作...
}
};
配置选项和标志位
枚举和位域结构体适合表示配置选项和标志位:
// 使用枚举类表示离散选项
enum class LogLevel {
Debug,
Info,
Warning,
Error,
Fatal
};
// 使用位域表示标志(可组合选项)
struct ConfigFlags {
unsigned int verbose : 1;
unsigned int showTimestamp : 1;
unsigned int colorOutput : 1;
unsigned int logToFile : 1;
unsigned int logToConsole : 1;
unsigned int asyncLogging : 1;
};
struct ApplicationConfig {
LogLevel level;
ConfigFlags flags;
std::string logFilePath;
int maxLogFileSize;
// 默认配置
ApplicationConfig()
: level(LogLevel::Info),
flags({
1, 1, 1, 1, 1, 0}), // 除asyncLogging外都启用
logFilePath("app.log"),
maxLogFileSize(10 * 1024 * 1024) // 10 MB
{
}
void setLogLevel(LogLevel newLevel) {
level = newLevel;
}
bool isDebugEnabled() const {
return level == LogLevel::Debug;
}
void enableVerboseOutput(bool enable) {
flags.verbose = enable ? 1 : 0;
}
};
几何图形计算
结构体非常适合表示和处理几何图形:
struct Point {
double x;
double y;
// 计算与另一点的距离
double distanceTo(const Point& other) const {
double dx = x - other.x;
double dy = y - other.y;
return std::sqrt(dx*dx + dy*dy);
}
};
struct Size {
double width;
double height;
};
struct Rectangle {
Point origin;
Size size;
// 计算面积
double area() const {
return size.width * size.height;
}
// 计算周长
double perimeter() const {
return 2 * (size.width + size.height);
}
// 判断点是否在矩形内
bool contains(const Point& p) const {
return p.x >= origin.x && p.x <= origin.x + size.width &&
p.y >= origin.y && p.y <= origin.y + size.height;
}
// 判断两个矩形是否相交
bool intersects(const Rectangle& other) const {
return !(origin.x + size.width < other.origin.x ||
other.origin.x + other.size.width < origin.x ||
origin.y + size.height < other.origin.y ||
other.origin.y + other.size.height < origin.y);
}
};
struct Circle {
Point center;
double radius;
double area() const {
return M_PI * radius * radius;
}
double circumference() const {
return 2 * M_PI * radius;
}
bool contains(const Point& p) const {
return center.distanceTo(p) <= radius;
}
};
最佳实践与设计考量
何时使用结构体vs类
- 使用结构体当主要目的是组织数据,尤其是当所有成员都应该是公有的时候
- 使用类当需要封装数据、限制访问、提供复杂接口或遵循更严格的面向对象设计原则时
何时使用传统枚举vs枚举类
- **使用枚举类(enum class)**是现代C++中的最佳实践,尤其是在新代码中
- 使用传统枚举主要是为了兼容旧代码,或者在需要隐式转换为整数的特定场合
组织相关数据
使用结构体组织相关数据,而不是使用多个独立变量:
// 不好的方式
std::string firstName;
std::string lastName;
int age;
std::string address;
std::string city;
std::string zipCode;
// 更好的方式
struct Person {
std::string firstName;
std::string lastName;
int age;
struct Address {
std::string street;
std::string city;
std::string zipCode;
};
Address address;
};
避免过大的结构体
过大的结构体可能导致性能问题和代码维护困难:
- 考虑将大型结构体拆分为更小的、逻辑相关的结构体
- 使用组合而非单个大结构体
- 考虑数据的访问模式,常用数据成员可以分组以优化缓存利用
设计清晰的枚举
设计枚举时的几点考虑:
- 为枚举和枚举器选择清晰、描述性的名称
- 考虑枚举值的顺序,尤其是当它们用于索引或排序时
- 适当注释枚举值的含义,特别是当含义不明显时
- 考虑是否需要"Invalid"或"Unknown"等值作为默认或错误情况
确保内存对齐适应硬件
为硬件优化结构体布局:
- 考虑按大小降序排列成员,以减少填充
- 使用对齐指令如果有特定硬件要求
- 了解目标平台的对齐要求
// 差的成员排序(有很多填充)
struct BadLayout {
char a; // 1字节 + 3字节填充
int b; // 4字节
char c; // 1字节 + 3字节填充
int d; // 4字节
}; // 总大小:16字节
// 更好的成员排序(最小化填充)
struct GoodLayout {
int b; // 4字节
int d; // 4字节
char a; // 1字节
char c; // 1字节
// 2字节填充以满足对齐
}; // 总大小:12字节
结构体与枚举的工具函数
打印结构体
可以为结构体实现流操作符重载以便于调试:
struct Person {
std::string name;
int age;
std::string city;
// 重载输出流操作符
friend std::ostream& operator<<(std::ostream& os, const Person& p) {
os << "Person{name='" << p.name << "', age=" << p.age
<< ", city='" << p.city << "'}";
return os;
}
};
// 使用方式
Person p = {
"Alice", 30, "New York"};
std::cout << p << std::endl;
枚举与字符串转换
为枚举值和字符串之间的转换提供辅助函数:
enum class Color {
Red,
Green,
Blue,
Yellow,
Purple
};
// 枚举转字符串
std::string colorToString(Color color) {
switch (color) {
case Color::Red: return "Red";
case Color::Green: return "Green";
case Color::Blue: return "Blue";
case Color::Yellow: return "Yellow";
case Color::Purple: return "Purple";
default: return "Unknown";
}
}
// 字符串转枚举(可选)
std::optional<Color> stringToColor(const std::string& str) {
if (str == "Red") return Color::Red;
if (str == "Green") return Color::Green;
if (str == "Blue") return Color::Blue;
if (str == "Yellow") return Color::Yellow;
if (str == "Purple") return Color::Purple;
return std::nullopt; // C++17
}
// 使用示例
Color c = Color::Blue;
std::cout << colorToString(c) << std::endl;
std::optional<Color> parsed = stringToColor("Green");
if (parsed) {
std::cout << "Parsed color: " << colorToString(*parsed) << std::endl;
}
总结
结构体和枚举是C++中用于组织和表示数据的重要工具。结构体允许将不同类型的数据组合成一个有意义的整体,而枚举则提供了一种创建命名常量集合的方式。
C++对这两种类型进行了扩展,结构体具有了面向对象的特性,支持成员函数、构造函数、继承等功能;而C++11引入的枚举类则解决了传统枚举的名称泄漏和类型安全性问题。
在实际编程中,根据数据的性质和使用场景,合理选择和使用结构体和枚举可以提高代码的可读性、可维护性和性能。尤其需要注意的是:
- 结构体适合组织相关数据,但需注意内存对齐和大小
- 现代C++中应优先使用枚举类而非传统枚举
- 结构体和枚举都可以扩展功能,如提供转换函数、操作符重载等
通过本文的学习,你应该能够在C++项目中熟练使用结构体和枚举,并根据实际需求选择合适的设计方案。
在下一篇文章中,我们将探讨面向对象编程中的类与对象,这是C++更为核心的特性之一。
参考资料
- Bjarne Stroustrup. The C++ Programming Language (4th Edition)
- Scott Meyers. Effective Modern C++
- cppreference.com - struct
- cppreference.com - enum
- C++ Core Guidelines - 枚举
- C++ Core Guidelines - 结构体
这是我C++学习之旅系列的第七篇技术文章。查看完整系列目录了解更多内容。