类
类的构造函数/析构函数可不可以私有?
是的,当你定义一个类数组,例如:
1 | class_A m[5]; |
✅ 会调用 class_A
的构造函数,并且会为每个元素调用一次!
当数组 m[5]
的作用域结束或被销毁,也会自动调用析构函数!
🧠 分析细节
假设你的类如下:
1 |
|
当你写:
1 | class_A m[2]; |
输出为:
1 | Default constructor called |
🟢 默认构造函数 class_A()
被调用 2次**,每个数组元素都进行一次构造。
❗注意情况 1:构造函数被删除(未定义)、带参数数组 或私有,不能默认构造
1 | class class_B { |
编译器会报错:
1 | error: no matching constructor for initialization of 'class_B' |
📌 原因:数组默认需要无参构造器来初始化每一个元素。
❗构造带参数数组
不能这样写:
1 | class_A m[5](1); // ❌ 错误语法 |
✅ 正确方式:
使用列表初始化或直接初始化各元素:
1 | class class_A { |
✅ 补充:析构函数也会被自动调用
当数组 m[5]
的作用域结束或被销毁:
- 会对每一个元素自动调用析构函数
- 调用顺序是 构造正序;析构反序
1 | class_A m[5]; // 构造顺序:m[0] 到 m[4] |
✅ 结论总结
语句 | 是否调用构造函数 | 调用次数 |
---|---|---|
class_A m[5]; |
✅ 是 | 调用默认构造函数5次 |
class_A m[5] = {...}; |
✅ 是 | 调用对应构造函数 |
类没有默认构造函数 | ❌ 编译失败 | |
构造构造失败 | ❌ 编译失败 | |
好的,我们来详细讲解 如何使用列表初始化来初始化一个类数组(也叫统一初始化,在 C++11 引入)。 |
✅ 假设你有如下类:
1 |
|
✅ 初始化类数组的方法:列表初始化(C++11及以上)
你可以用花括号 统一初始化整个数组中的每个对象:
1 | MyClass arr[3] = { {1}, {2}, {3} }; |
🔍 实际做了什么?
这会调用带参数的构造函数:
MyClass(1)
MyClass(2)
MyClass(3)
✅ 相当于如下初始化方式:
1 | MyClass arr[3] = { MyClass(1), MyClass(2), MyClass(3) }; |
🔎 如果构造函数还有多个参数:
1 | class MyClass { |
你可以这样初始化数组:
1 | MyClass arr[2] = { {1, 2}, {3, 4} }; |
✅ 动态数组初始化(vector + 列表初始化)
更现代和灵活的方式是使用 std::vector
替代数组:
1 |
|
这种方式可以动态扩展,不必提前指定大小,而且初始化语法更直观。
✅ 总结:类数组的列表初始化要点:
- 你可以使用
{ {arg1}, {arg2}, ... }
块初始化数组中的每个对象 - 必须调用匹配的构造函数
- 如果数量不足,剩余元素必须能调用默认构造函数,否则会编译错误
- 推荐使用
std::vector<T>
动态管理对象列表,更安全灵活
动态分配方法(new[]
)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Min的博客!
评论