C++中的构造函数

在C++中,构造函数是类中用于初始化对象的特殊成员函数。它们与类同名,没有返回类型(连void也没有)。以下是C++中常见的构造函数类型:

1. 默认构造函数

  • 定义:不带参数或所有参数有默认值的构造函数。
  • 作用:创建对象时无需提供初始值。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    class MyClass {
    public:
    MyClass() { x = 0; } // 默认构造函数
    private:
    int x;
    };
    MyClass obj; // 调用默认构造函数

2. 参数化构造函数

  • 定义:带参数的构造函数,用于初始化对象的成员。
  • 作用:允许通过参数传递初始值。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    class MyClass {
    public:
    MyClass(int val) : x(val) {} // 参数化构造函数
    private:
    int x;
    };
    MyClass obj(10); // 调用参数化构造函数

3. 拷贝构造函数

  • 定义:以同类型对象的引用作为参数,用于从现有对象复制构造新对象。
  • 作用:实现对象深拷贝或自定义拷贝行为。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    class MyClass {
    public:
    MyClass(const MyClass& other) : x(other.x) {} // 拷贝构造函数
    private:
    int x;
    };
    MyClass obj1(5);
    MyClass obj2(obj1); // 调用拷贝构造函数

4. 移动构造函数(C++11起)

  • 定义:以右值引用(&&)为参数,转移资源所有权。
  • 作用:优化性能,避免深拷贝,适合临时对象。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    class MyClass {
    public:
    MyClass(MyClass&& other) noexcept : x(other.x) { other.x = 0; } // 移动构造函数
    private:
    int x;
    };
    MyClass obj1(5);
    MyClass obj2(std::move(obj1)); // 调用移动构造函数

5. 委托构造函数(C++11起)

  • 定义:一个构造函数调用另一个构造函数来完成部分初始化。
  • 作用:减少代码重复。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    class MyClass {
    public:
    MyClass() : MyClass(0) {} // 委托构造函数
    MyClass(int val) : x(val) {}
    private:
    int x;
    };
    MyClass obj; // 调用默认构造函数,委托给参数化构造函数

6. 转换构造函数

  • 定义:单个参数的构造函数(非explicit),可用于类型转换。
  • 作用:允许从指定类型隐式转换到类类型。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    class MyClass {
    public:
    MyClass(int val) : x(val) {} // 转换构造函数
    private:
    int x;
    };
    MyClass obj = 10; // 隐式转换调用转换构造函数

7. 显式构造函数(使用explicit

  • 定义:用explicit关键字修饰,禁止隐式转换。
  • 作用:防止意外的类型转换。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    class MyClass {
    public:
    explicit MyClass(int val) : x(val) {} // 显式构造函数
    private:
    int x;
    };
    MyClass obj(10); // 正确
    // MyClass obj = 10; // 错误:禁止隐式转换

注意事项

  • 编译器生成的构造函数
    • 如果未定义任何构造函数,编译器会生成默认构造函数。
    • 如果定义了其他构造函数,默认构造函数不会自动生成。
    • 拷贝构造函数和移动构造函数在特定条件下(如无用户定义)由编译器生成。
  • 初始化列表:构造函数常使用初始化列表(如: x(val))来高效初始化成员。
  • 禁用构造函数:可用delete关键字禁用特定构造函数(如MyClass(const MyClass&) = delete;)。
  • 虚继承与构造函数:在虚继承中,虚基类的构造函数由最底层的派生类负责调用。

示例综合代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
class MyClass {
public:
// 默认构造函数
MyClass() : x(0) { std::cout << "Default constructor\n"; }

// 参数化构造函数
MyClass(int val) : x(val) { std::cout << "Parameterized constructor\n"; }

// 拷贝构造函数
MyClass(const MyClass& other) : x(other.x) { std::cout << "Copy constructor\n"; }

// 移动构造函数
MyClass(MyClass&& other) noexcept : x(other.x) {
other.x = 0;
std::cout << "Move constructor\n";
}

// 转换构造函数
explicit MyClass(double val) : x(static_cast<int>(val)) { std::cout << "Conversion constructor\n"; }

void print() { std::cout << "x = " << x << "\n"; }
private:
int x;
};

int main() {
MyClass obj1; // 默认构造函数
MyClass obj2(10); // 参数化构造函数
MyClass obj3(obj2); // 拷贝构造函数
MyClass obj4(std::move(MyClass(20))); // 移动构造函数
MyClass obj5(5.5); // 转换构造函数
// MyClass obj6 = 5.5; // 错误:explicit禁止隐式转换

obj1.print();
obj2.print();
obj3.print();
obj4.print();
obj5.print();
return 0;
}

输出

1
2
3
4
5
6
7
8
9
10
11
Default constructor
Parameterized constructor
Copy constructor
Parameterized constructor
Move constructor
Conversion constructor
x = 0
x = 10
x = 10
x = 20
x = 5

这些构造函数类型覆盖了C++中对象初始化的各种场景,根据需求选择合适的构造函数能提高代码效率和安全性。