C++ 构造函数:默认构造函数与参数构造函数
构造函数是 C++ 中一种特殊的成员函数,它的名字与类名完全相同,并且没有返回值。每当创建一个类的对象时,编译器都会自动调用构造函数,用于初始化对象的数据成员。理解并掌握默认构造函数与参数构造函数,是编写健壮 C++ 代码的基础。
一、 理解默认构造函数
默认构造函数是指在调用时不需要提供任何参数的构造函数。它主要用于将对象初始化为一个合理的默认状态。
-
识别默认构造函数的两种形式:
- 定义一个没有任何参数的构造函数。
- 如果没有定义任何构造函数,编译器会自动生成一个隐式的默认构造函数(该函数体为空,不做任何事,但不会报错)。
-
编写显式默认构造函数代码:
打开代码编辑器,输入以下代码:
#include <iostream>
#include <string>
using namespace std;
class Box {
public:
// 默认构造函数
Box() {
length = 0.0;
width = 0.0;
height = 0.0;
cout << "默认构造函数已被调用:盒子尺寸初始化为 0" << endl;
}
// 用于显示尺寸的成员函数
void printDimensions() {
cout << "长: " << length << ", 宽: " << width << ", 高: " << height << endl;
}
private:
double length;
double width;
double height;
};
int main() {
// 调用默认构造函数
Box box1;
box1.printDimensions();
return 0;
}
- 编译并运行上述代码。观察控制台输出,确认对象
box1在创建时自动将长宽高设为了0.0。
二、 掌握参数构造函数
参数构造函数允许在创建对象时传入特定数值,从而将对象初始化为指定的状态。这比创建对象后再逐个赋值要高效且安全。
-
理解参数传递机制:
构造函数可以像普通函数一样接受参数。参数列表定义在构造函数名后的圆括号内,参数个数和类型由需求决定。 -
编写参数构造函数代码:
继续在刚才的代码中添加一个新的构造函数:
class Box {
public:
// 默认构造函数(保留之前的)
Box() {
length = 0.0;
width = 0.0;
height = 0.0;
cout << "默认构造函数已被调用" << endl;
}
// 参数构造函数
Box(double l, double w, double h) {
length = l;
width = w;
height = h;
cout << "参数构造函数已被调用:尺寸已设定" << endl;
}
void printDimensions() {
cout << "长: " << length << ", 宽: " << width << ", 高: " << height << endl;
}
private:
double length;
double width;
double height;
};
- 修改
main函数以测试参数构造函数:
int main() {
// 调用默认构造函数
Box box1;
box1.printDimensions();
cout << "--------" << endl;
// 调用参数构造函数
Box box2(10.5, 5.2, 3.0);
box2.printDimensions();
return 0;
}
- 运行程序。你将看到
box1使用默认值,而box2使用了你传入的10.5、5.2和3.0。
三、 构造函数的选择逻辑(流程图)
当我们在代码中声明一个对象时,编译器会根据传入的参数数量和类型来决定调用哪一个构造函数。这个过程称为“构造函数重载解析”。
以下流程图描述了编译器的选择逻辑:
四、 关键区别与使用场景对比
为了更清晰地展示两者差异,请参考下表。
| 特性 | 默认构造函数 | 参数构造函数 |
|---|---|---|
| 调用方式 | ClassName obj; |
ClassName obj(arg1, arg2); |
| 参数要求 | 无需传入参数 | 必须传入匹配类型和数量的参数 |
| 典型用途 | 创建数组元素、作为容器元素、初始化为标准默认值 | 根据具体需求定制对象的初始状态 |
| 编译器行为 | 仅当未定义任何构造函数时自动生成 | 永远不会自动生成,必须手动定义 |
五、 进阶注意事项:构造函数的“屏蔽”效应
这是一个初学者常犯的错误。一旦你定义了任何一个参数构造函数,编译器就会停止生成默认的构造函数。
- 观察以下代码错误场景:
假设代码中只有 Box(double l, double w, double h) 这一个构造函数。
int main() {
// 尝试调用默认构造函数
Box box3; // 这里会报错!
return 0;
}
-
分析错误原因:
因为你定义了参数构造函数,编译器认为你不需要隐式的默认构造函数,因此删除了它。此时Box box3;找不到对应的构造函数执行。 -
解决问题:
如果你同时需要无参初始化和带参初始化,必须显式地把两个构造函数都写出来,就像第二部分代码中展示的那样。
六、 使用初始化列表优化参数构造函数
在参数构造函数中,给成员变量赋值除了在函数体内用 = 赋值外,更推荐使用“初始化列表”。这在某些情况下(如 const 成员或引用成员)是必须的,且效率更高。
- 修改参数构造函数写法:
将代码:
Box(double l, double w, double h) {
length = l;
width = w;
height = h;
}
改为:
Box(double l, double w, double h) : length(l), width(w), height(h) {
// 函数体可以为空,或者执行其他初始化逻辑
}
-
对比两者:
修改后的写法中,: length(l), width(w), height(h)就是初始化列表。它直接在对象构造时初始化了成员变量,避免了先构造再赋值的开销。 -
编译并验证,功能完全一致,但代码执行效率更优。

暂无评论,快来抢沙发吧!