C++中class与struct的异同点深度解析
一、基础语法差异
1.1 访问修饰符差异
- class 默认成员访问权限为
private
- 声明的成员变量与函数仅对类内部可见,需使用
public
/protected
显式开放
- 声明的成员变量与函数仅对类内部可见,需使用
- struct 默认成员访问权限为
public
- 结构体成员对所有作用域开放,需使用
private
/protected
显式限制
- 结构体成员对所有作用域开放,需使用
1 | class MyClass { |
1.2 成员函数特性
- class 支持抽象方法(纯虚函数)
- 通过
= 0
定义的虚函数使类成为抽象类,如virtual void func() = 0;
- 通过
- struct 不支持抽象方法
- 所有成员函数必须有具体实现,否则会导致编译错误
1 | class AbstractClass { |
1.3 构造函数行为
- class 必须显式定义构造函数
- 提供默认构造函数需使用
MyClass() {}
显式声明
- 提供默认构造函数需使用
- struct 可以省略构造函数
- 编译器会自动合成默认构造函数
1 | class MyClass { |
1.4 继承机制差异
- class:传统支持多继承(C++继承机制默认为 private)
- struct:C++11后支持多继承(继承方式默认为 public)
- 例如:
struct Derived : Base1, Base2 { };
合法
- 例如:
1 | struct Base1 {}; |
二、实现机制解析
2.1 内存布局差异
- 类与结构体同构:成员变量按声明顺序排列,遵循内存对齐规则
- 差异点:类中隐式包含的虚函数表指针(
vptr
)会导致额外内存开销- 例如:带有虚函数的类会包含一个
vptr
成员,而结构体通常不包含该指针
- 例如:带有虚函数的类会包含一个
1 | struct Data { |
2.2 类型转换机制
- class 的构造函数默认参与隐式类型转换
- 编译器可将构造函数视为转换运算符,如
MyClass obj = 42;
- 编译器可将构造函数视为转换运算符,如
- struct 的构造函数也默认参与隐式类型转换
- 但可通过
explicit
限制转换行为
- 但可通过
1 | class MyClass { |
2.3 名字遮蔽规则
- 类与结构体统一遵循:子类同名成员遮蔽基类成员
- 差异点:结构体在继承中可定义同名构造函数,其行为与基类构造函数差异化
- 例如:
struct Derived : Base { Derived() {} };
会遮蔽Base
的构造函数
- 例如:
1 | struct Base { |
2.4 编译器优化策略
- 内存对齐差异:编译器可能对结构体应用更严格的对齐规则
- 性能差异:结构体的默认构造函数合成效率通常高于类
- 实现细节:某些编译器(如MSVC)对结构体的内存布局可能更紧凑
1 | // 结构体可能导致更紧凑的内存布局 |
三、应用场景对比
3.1 数据封装场景
- class 适用性:需要封装数据与行为的完整对象
- 示例:
class Student { private: int id; public: void study() {} };
- 示例:
- struct 适用性:纯数据结构(C++11优化后适用复杂场景)
- 示例:
struct Point { int x; int y; };
- 示例:
3.2 继承体系构建
- class 适用性:构建复杂的继承树,支持多继承与多态
- 示例:
class Shape { virtual void draw() {} }; class Circle : Shape { void draw() override {} };
- 示例:
- struct 适用性:支持多继承但通常用于非多态场景
- 示例:
struct Shape { virtual void draw() {} }; struct Square : Shape { void draw() override {} };
- 示例:
3.3 代码设计模式
- Pimpl惯用法:class更适合封装实现细节
- 示例:
class MyClass { private: std::unique_ptr<Implementation> pimpl; };
- 示例:
- 值类型设计:struct更适合轻量级值类型(C++11后适用)
- 示例:
struct MyValue { int a; int b; };
- 示例:
3.4 性能敏感场景
- class 适用性:结构复杂时可能不适用于性能关键路径
- struct 适用性:内存占用更少,更适合底层数据处理
- 示例:
struct Buffer { unsigned char data[1024]; };
- 示例:
四、核心差异总结
特性 | class | struct |
---|---|---|
默认访问权限 | private | public |
抽象方法支持 | 支持 | 不支持 |
默认构造函数 | 需显式声明或合成 | 自动合成 |
虚函数表 | 含有(若定义虚函数) | 通常不含 |
隐式转换 | 支持 | 支持(可通过explicit限制) |
继承方式 | 传统使用public继承 | C++11后支持public继承 |
编译器处理 | 按标准严格处理 | 可能有更紧凑的优化 |
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.