目录
[学习日志|Day 5](#学习日志|Day 5)
[二、C 语言 struct:只有"数据的集合"](#二、C 语言 struct:只有“数据的集合”)
[三、C++ struct:本质上就是"默认 public 的 class"](#三、C++ struct:本质上就是“默认 public 的 class”)
[3.1 C++ 的 struct 完整支持类的所有能力](#3.1 C++ 的 struct 完整支持类的所有能力)
[四、C++ struct vs class:真正只有 2 个语法差异](#四、C++ struct vs class:真正只有 2 个语法差异)
[4.1 默认成员访问权限不同](#4.1 默认成员访问权限不同)
[4.2 默认继承方式不同](#4.2 默认继承方式不同)
[4.3 总结](#4.3 总结)
[五、工程实践---为什么强烈建议"数据用 struct,逻辑用 class"?](#五、工程实践—为什么强烈建议“数据用 struct,逻辑用 class”?)
[5.1 继承访问控制差异在工程中几乎没有意义](#5.1 继承访问控制差异在工程中几乎没有意义)
[5.2 工程规范中:class 成员变量都必须是 private](#5.2 工程规范中:class 成员变量都必须是 private)
[5.3 为什么要用 struct 存储数据结构?](#5.3 为什么要用 struct 存储数据结构?)
[5.4 工程最佳实践总结](#5.4 工程最佳实践总结)
[六、模板深度八股:class / typename / struct 的真实区别](#六、模板深度八股:class / typename / struct 的真实区别)
[6.1 在模板参数列表里:class = typename](#6.1 在模板参数列表里:class = typename)
[6.2 模板内部遇到"依赖类型"时,必须用 typename](#6.2 模板内部遇到“依赖类型”时,必须用 typename)
[6.3 为什么不能写 class T::type?](#6.3 为什么不能写 class T::type?)
[6.4 总结(推荐直接背下来)](#6.4 总结(推荐直接背下来))
[7.1 面试官问:C 语言 struct 与 C++ struct 有什么区别?](#7.1 面试官问:C 语言 struct 与 C++ struct 有什么区别?)
[7.2 面试官问:C++ struct 和 class 有什么区别?](#7.2 面试官问:C++ struct 和 class 有什么区别?)
[8.1 C struct vs C++ struct](#8.1 C struct vs C++ struct)
[8.2 C++ struct vs class](#8.2 C++ struct vs class)
学习日志|Day 5
第五篇文章主要梳理了**struct 与 class,**包含:
-
C 语言 struct vs C++ struct 的本质区别
-
C++ struct vs class 的核心差异
-
工程实践中为什么 struct 经常用来做"纯数据结构"
-
模板 typename 与 class 的真实差异
-
为什么 class 一般禁止 public 成员变量

一、前言
在大厂 C/C++ 面试(尤其是华为、字节、OPPO、蔚来等)中,"struct 与 class 的区别"几乎是 必问高频题。
很多人只记得一句:
struct 和 class 只有默认访问权限不同。
这句话是对的,但远远不够拿高分。
写文章的目的是让读者们从 语言设计 → 语法本质 → 工程实践 → 规范约定 全面了解,让大家彻底吃透这个八股知识点。
二、C 语言 struct:只有"数据的集合"
C struct 的核心特征:
✔ 只能包含 成员变量
✔ 不能有 成员函数
✔ 不能有 构造 / 析构函数
✔ 不能有 继承、多态、虚函数
✔ 不能是空结构体(必须至少 1 个成员)
✔ 本质是一块内存布局描述
示例:
cs
struct Msg {
int id;
char data[32];
};
C 的 struct 完全是 面向过程 的产物,用来组织一组相关数据。
三、C++ struct:本质上就是"默认 public 的 class"
这是很多人忽略的重点:
3.1 C++ 的 struct 完整支持类的所有能力
✔ 可以有成员函数
✔ 可以有构造 / 析构函数
✔ 可以有 static
✔ 可以继承
✔ 可以多态
✔ 可以模板
✔ 可以为空(sizeof = 1)
看个例子:
cpp
struct Msg {
int id{0};
std::string str;
Msg() {} // 构造
void dump() {} // 成员函数
};
这在 C 里完全不可能。
👉 结论:C++ struct 的能力 = class 的能力
四、C++ struct vs class:真正只有 2 个语法差异
4.1 默认成员访问权限不同
| 关键字 | 默认权限 |
|---|---|
| struct | public |
| class | private |
cpp
struct A { int x; }; // public
class B { int x; }; // private
4.2 默认继承方式不同
| 继承写法 | 默认继承方式 |
|---|---|
| struct Base | public |
| class Base | private |
4.3 总结
你可以把一句话背下来:
除了默认权限与默认继承方式外,struct 与 class 100% 等价。
五、工程实践---为什么强烈建议"数据用 struct,逻辑用 class"?
5.1 继承访问控制差异在工程中几乎没有意义
正规 C++ 代码规范中,继承必须:
cpp
class Derived : public Base
团队代码规范一般都要求:
继承一律用 public,private/protected 继承禁止使用
因此:
struct 的"默认 public 继承"几乎没有价值
5.2 工程规范中:class 成员变量都必须是 private
几乎所有 C++ 规范都要求:
只要用 class,则所有成员变量必须设为 private
访问必须通过 getter/setter 或接口完成
原因:
-
需要保持封装性
-
维护类的行为边界
-
防止外部随意改内部状态
-
易于调试、扩展、加逻辑
所以在工程中看到 class,就会默认:
类的内部状态不允许被外部直接访问
成员变量必须通过函数来访问
5.3 为什么要用 struct 存储数据结构?
当我们只想存 数据本身,不需要封装性时,例如:
-
通信消息
-
算法节点数据
-
配置表
-
POD(plain old data)
-
结构化缓存数据
-
返回多个值的简单结构
-
JSON / msgpack / protobuf 中间结构
这时如果用 class:
❌ 需要写 getter/setter
❌ 访问太麻烦
❌ 多余的封装
而 struct:
✔ 默认 public
✔ 可以直接访问成员
✔ 语义更轻量级
✔ 一眼就能看出"这是纯数据结构"
例如:
cpp
class MsgServer
{
public:
struct Msg
{
int id{0};
string str;
};
void SendMsg(const Msg& msg);
};
结构体 只存数据,不存行为,符合 80% 工程里的纯数据场景。
5.4 工程最佳实践总结
| 场景 | 建议使用 |
|---|---|
| 需要封装逻辑、行为、生命周期管理 | class(成员变量 private) |
| 纯数据结构,不需要封装 | struct(成员变量 public) |
| 数据 + 方法混用、存在逻辑边界 | class |
| POD(Plain Old Data)类型 | struct |
| 简单算法数据容器 | struct |
| 协议消息 / 序列化数据 | struct |
六、模板深度八股:class / typename / struct 的真实区别
大部分人完全搞不清这里,但在中高级面试非常常问。
6.1 在模板参数列表里:class = typename
以下写法完全等价:
cpp
template<class T>
template<typename T>
template<class T, typename U>
甚至可以写:
cpp
template<struct T> // 语法合法,但没人这么写
原因:
它们都只是告诉编译器"这是模板参数类型"。
6.2 模板内部遇到"依赖类型"时,必须用 typename
看例子:
cpp
template <class T>
void foo(T a)
{
typename T::value_type x; // 必须 typename
}
如果你没有写 typename:
cpp
T::value_type x; // ❌ 编译器不知道 value_type 是类型还是静态成员
编译器会误认为 value_type 是变量或静态成员。
所以必须写:
cpp
typename T::value_type x; // 告诉编译器,这是一个类型
这就是著名的:
dependent type(依赖类型)需要 typename 修饰
6.3 为什么不能写 class T::type?
因为 class 不能用在"类型使用位置",只能用来:
-
定义类
-
模板参数列表
它不能替代 typename:
cpp
class T::value_type x; // ❌ 非法
6.4 总结(推荐直接背下来)
在模板参数列表中,class 与 typename 完全等价。
但在模板内部,当出现依赖模板参数的类型(T::xxx)时,必须使用 typename 告诉编译器"这是一个类型"。
struct 也能写为模板类型参数,但毫无语义价值,工程不用。
七、核心总结:拿满面试分的回答
7.1 面试官问:C 语言 struct 与 C++ struct 有什么区别?
你可以这样答:
C 的 struct 是纯数据集合,不能有成员函数、不能空、不能继承、不能多态。
C++ 的 struct 本质上就是默认 public 的 class,支持完整的面向对象能力:构造析构、成员函数、继承、多态、模板等都能用。
两者的能力差距本质上是语言范式差异:C 是面向过程;C++ 是面向对象。
7.2 面试官问:C++ struct 和 class 有什么区别?
最标准的满分回答:
struct 和 class 的唯一语法区别是默认权限不同(struct 是 public,class 是 private)以及默认继承方式不同。其他能力完全一样。
在工程实践中,我们通常约定:
class 管行为 + 封装,成员变量必须 private;
struct 用来存储纯数据结构,不写成员函数,所有成员默认 public。
所以 struct 是轻量级的数据容器,而 class 是具备封装性的对象。
八、张总结表格(面试必杀)
8.1 C struct vs C++ struct
| 特性 | C struct | C++ struct |
|---|---|---|
| 成员变量 | ✔ | ✔ |
| 成员函数 | ✘ | ✔ |
| 构造/析构 | ✘ | ✔ |
| 继承、多态 | ✘ | ✔ |
| 空结构体 | ✘ | ✔(sizeof=1) |
| 本质 | 数据容器 | class 的 public 类型 |
8.2 C++ struct vs class
| 对比项 | struct | class |
|---|---|---|
| 默认成员权限 | public | private |
| 默认继承方式 | public | private |
| 能力差异 | 完全一致 | 完全一致 |
| 工程语义 | 纯数据结构 | 封装行为的对象 |
| 成员函数 | 可有但建议不要有 | 常见 |
九、总结
在 C 中,struct 是"数据结构";
在 C++ 中,struct 是"默认 public 的 class";
在工程中,struct 用来存数据,class 用来做对象。