文章目录

C++ 构造函数:默认构造函数与参数构造函数

发布于 2026-04-15 01:18:25 · 浏览 23 次 · 评论 0 条

C++ 构造函数:默认构造函数与参数构造函数

构造函数是 C++ 中一种特殊的成员函数,它的名字与类名完全相同,并且没有返回值。每当创建一个类的对象时,编译器都会自动调用构造函数,用于初始化对象的数据成员。理解并掌握默认构造函数与参数构造函数,是编写健壮 C++ 代码的基础。


一、 理解默认构造函数

默认构造函数是指在调用时不需要提供任何参数的构造函数。它主要用于将对象初始化为一个合理的默认状态。

  1. 识别默认构造函数的两种形式:

    • 定义一个没有任何参数的构造函数。
    • 如果没有定义任何构造函数,编译器会自动生成一个隐式的默认构造函数(该函数体为空,不做任何事,但不会报错)。
  2. 编写显式默认构造函数代码:

打开代码编辑器,输入以下代码:

#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;
}
  1. 编译并运行上述代码。观察控制台输出,确认对象 box1 在创建时自动将长宽高设为了 0.0

二、 掌握参数构造函数

参数构造函数允许在创建对象时传入特定数值,从而将对象初始化为指定的状态。这比创建对象后再逐个赋值要高效且安全。

  1. 理解参数传递机制:
    构造函数可以像普通函数一样接受参数。参数列表定义在构造函数名后的圆括号内,参数个数和类型由需求决定。

  2. 编写参数构造函数代码:

继续在刚才的代码中添加一个新的构造函数:

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;
};
  1. 修改 main 函数以测试参数构造函数:
int main() {
    // 调用默认构造函数
    Box box1;
    box1.printDimensions();

    cout << "--------" << endl;

    // 调用参数构造函数
    Box box2(10.5, 5.2, 3.0);
    box2.printDimensions();

    return 0;
}
  1. 运行程序。你将看到 box1 使用默认值,而 box2 使用了你传入的 10.55.23.0

三、 构造函数的选择逻辑(流程图)

当我们在代码中声明一个对象时,编译器会根据传入的参数数量和类型来决定调用哪一个构造函数。这个过程称为“构造函数重载解析”。

以下流程图描述了编译器的选择逻辑:

graph TD A["开始: 声明对象"] --> B{是否提供参数?} B -- 否 --> C["查找默认构造函数"] B -- 是 --> D{参数类型/数量匹配?} D -- 否 --> E["编译错误"] D -- 是 --> F["调用对应的参数构造函数"] C --> G["初始化对象为默认值"] F --> H["初始化对象为指定值"]

四、 关键区别与使用场景对比

为了更清晰地展示两者差异,请参考下表。

特性 默认构造函数 参数构造函数
调用方式 ClassName obj; ClassName obj(arg1, arg2);
参数要求 无需传入参数 必须传入匹配类型和数量的参数
典型用途 创建数组元素、作为容器元素、初始化为标准默认值 根据具体需求定制对象的初始状态
编译器行为 仅当未定义任何构造函数时自动生成 永远不会自动生成,必须手动定义

五、 进阶注意事项:构造函数的“屏蔽”效应

这是一个初学者常犯的错误。一旦你定义了任何一个参数构造函数,编译器就会停止生成默认的构造函数。

  1. 观察以下代码错误场景:

假设代码中只有 Box(double l, double w, double h) 这一个构造函数。

int main() {
    // 尝试调用默认构造函数
    Box box3; // 这里会报错!
    return 0;
}
  1. 分析错误原因:
    因为你定义了参数构造函数,编译器认为你不需要隐式的默认构造函数,因此删除了它。此时 Box box3; 找不到对应的构造函数执行。

  2. 解决问题:
    如果你同时需要无参初始化和带参初始化,必须显式地把两个构造函数都出来,就像第二部分代码中展示的那样。


六、 使用初始化列表优化参数构造函数

在参数构造函数中,给成员变量赋值除了在函数体内用 = 赋值外,更推荐使用“初始化列表”。这在某些情况下(如 const 成员或引用成员)是必须的,且效率更高。

  1. 修改参数构造函数写法:

将代码:

    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) {
        // 函数体可以为空,或者执行其他初始化逻辑
    }
  1. 对比两者:
    修改后的写法中,: length(l), width(w), height(h) 就是初始化列表。它直接在对象构造时初始化了成员变量,避免了先构造再赋值的开销。

  2. 编译并验证,功能完全一致,但代码执行效率更优。

评论 (0)

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

扫一扫,手机查看

扫描上方二维码,在手机上查看本文