💡 一分钟速览:通过可编译示例比较 C++ struct 与 class 的默认成员访问、默认继承方式,并说明何时选择两者以及聚合类型的常见误解。
最后更新:2026-10-13
C++ struct 与 class 有什么区别?¶
在 C++ 中,两者都定义类类型,都支持构造函数、成员函数、模板、继承和虚函数。语言规则上的区别是**成员的默认访问权限**和**基类的默认继承方式**;团队中的用法习惯是另一回事。
| 省略访问说明时 | struct |
class |
|---|---|---|
| 成员 | public |
private |
| 基类 | public |
private |
成员访问:第一个默认值¶
struct Open {
int value = 1; // 默认 public
};
class Closed {
int value = 1; // 默认 private
public:
int get() const { return value; }
};
int main() {
Open a;
Closed b;
// b.value = 2; // 错误:私有成员
return a.value == b.get() ? 0 : 1;
}
显式写出 public: 或 private: 就会覆盖默认值。struct 可以隐藏成员,class 也可以公开成员。关于 C 语言结构体及名称查找的更多区别,参见 C 与 C++ 的 struct。
继承方式:第二个默认值¶
#include <type_traits>
struct Base {};
struct PublicChild : Base {}; // 等同于 : public Base
class PrivateChild : Base {}; // 等同于 : private Base
static_assert(std::is_base_of_v<Base, PublicChild>);
static_assert(std::is_base_of_v<Base, PrivateChild>);
static_assert(std::is_convertible_v<PublicChild*, Base*>);
static_assert(!std::is_convertible_v<PrivateChild*, Base*>);
int main() {}
用 c++ -std=c++17 -Wall -Wextra struct_class.cpp 编译。PrivateChild 依然继承了 Base,只是外部代码不能隐式地把它的指针转成 Base*。在公开接口中,若继承方式对读者有意义,建议明确写出 public 或 private。
struct 一定是纯数据聚合吗?¶
不是。“公开的数据记录用 struct,维护不变量的类型用 class”是一种常见约定。是否为聚合类型还取决于构造函数、访问权限、基类及虚函数等条件,不能只看关键字。下面两个类型在 C++17 中都是聚合:
#include <type_traits>
struct Point { int x; int y; };
class Pair {
public:
int first;
int second;
};
static_assert(std::is_aggregate_v<Point>);
static_assert(std::is_aggregate_v<Pair>);
int main() {
Point p{1, 2};
Pair q{1, 2};
return p.x == q.first ? 0 : 1;
}
实际如何选择?¶
- 成员本来就是公开接口的简单数据记录,通常用
struct。 - 需要通过操作维护不变量、限制成员的直接修改,通常用
class。 - 不要让读者猜公开 API 的访问或继承意图;有必要时显式写出权限。
关键字本身不会带来特殊性能,也不会把 C++ 类型变成“C 风格结构体”。进一步阅读 explicit 转换和智能指针函数参数。
参考资料¶
关于作者¶
个人公众号:

相关主题¶
- C++ 纯虚函数与抽象类 | C++那些事
- C++ assert 断言 | C++那些事
- C++ 位域 | C++那些事
- C 语言实现 C++ 多态 | C++那些事
- C++ const 详解:常量、常量指针与指针常量的区别 | C++那些事
- C++ const 全家桶 | C++那些事
- C++ 解引用运算符 * | C++那些事
- C++ 初始化与赋值 | C++那些事
- C++ 多返回值写法 | C++那些事
- C++ mutable 关键字 | C++那些事