构造函数(Constructor)是 C++ 类的一种特殊成员函数,在创建类对象时自动调用,用于初始化对象的成员变量。构造函数的名字与类名相同,没有返回值。
1. 构造函数的基本特点
- 名字与类名相同。
- 没有返回值(包括
void
)。 - 在对象创建时自动调用。
- 可以被重载(通过不同的参数列表实现)。
- 如果没有显式定义构造函数,编译器会提供一个默认构造函数。
2. 构造函数的类型
2.1 默认构造函数
- 没有参数或所有参数都有默认值的构造函数。
- 编译器会自动提供一个默认构造函数,如果没有定义其他构造函数。
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass() { // 默认构造函数
cout << "Default constructor called" << endl;
}
};
int main() {
MyClass obj; // 自动调用默认构造函数
return 0;
}
输出:
Default constructor called
2.2 有参构造函数
- 接受参数,用于根据传入的值初始化对象。
#include <iostream>
using namespace std;
class MyClass {
int value;
public:
MyClass(int val) { // 有参构造函数
value = val;
cout << "Parameterized constructor called with value: " << value << endl;
}
};
int main() {
MyClass obj(10); // 自动调用有参构造函数
return 0;
}
输出:
Parameterized constructor called with value: 10
2.3 拷贝构造函数
- 用于根据已有对象创建新对象,完成对象的拷贝。
- 如果没有定义,编译器会生成默认的拷贝构造函数(浅拷贝)。
#include <iostream>
using namespace std;
class MyClass {
int value;
public:
MyClass(int val) : value(val) {} // 有参构造函数
// 拷贝构造函数
MyClass(const MyClass& other) {
value = other.value;
cout << "Copy constructor called" << endl;
}
void display() {
cout << "Value: " << value << endl;
}
};
int main() {
MyClass obj1(10); // 调用有参构造函数
MyClass obj2 = obj1; // 调用拷贝构造函数
obj2.display();
return 0;
}
输出:
Copy constructor called
Value: 10
2.4 委托构造函数(C++11)
- 一个构造函数调用另一个构造函数,减少重复代码。
#include <iostream>
using namespace std;
class MyClass {
int value;
public:
// 主构造函数
MyClass(int val) : value(val) {}
// 委托构造函数
MyClass() : MyClass(0) { // 调用 MyClass(int)
cout << "Delegating constructor called" << endl;
}
void display() {
cout << "Value: " << value << endl;
}
};
int main() {
MyClass obj; // 调用委托构造函数
obj.display();
return 0;
}
输出:
Delegating constructor called
Value: 0
2.5 默认构造函数(C++11)
- 使用
= default
明确要求编译器生成默认构造函数。
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass() = default; // 显式声明默认构造函数
};
int main() {
MyClass obj;
return 0;
}
2.6 禁用构造函数(C++11)
- 使用
= delete
禁止特定的构造函数。
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass() = delete; // 禁止默认构造函数
MyClass(int val) { // 允许有参构造函数
cout << "Constructor with value: " << val << endl;
}
};
int main() {
// MyClass obj; // 错误,默认构造函数被删除
MyClass obj(10); // 正常调用
return 0;
}
3. 构造函数的调用顺序
- 单继承:基类的构造函数先执行,然后执行派生类的构造函数。
- 多继承:多个基类的构造函数按声明顺序执行,然后执行派生类的构造函数。
- 成员对象:成员对象的构造函数在外部类构造函数之前执行,按成员声明顺序调用。
示例:
#include <iostream>
using namespace std;
class Base {
public:
Base() {
cout << "Base constructor" << endl;
}
};
class Member {
public:
Member() {
cout << "Member constructor" << endl;
}
};
class Derived : public Base {
Member m;
public:
Derived() {
cout << "Derived constructor" << endl;
}
};
int main() {
Derived obj;
return 0;
}
输出:
Base constructor
Member constructor
Derived constructor
4. 初始化列表
初始化列表用于在构造函数中直接初始化类的成员变量,效率更高。
初始化列表的优点
- 避免了默认构造和赋值的二次操作。
- 对于
const
或引用类型的成员变量,初始化列表是唯一的方法。
示例:
#include <iostream>
using namespace std;
class MyClass {
const int x; // 常量成员
int& ref; // 引用成员
public:
MyClass(int val, int& r) : x(val), ref(r) { // 初始化列表
cout << "Constructor called" << endl;
}
void display() {
cout << "x: " << x << ", ref: " << ref << endl;
}
};
int main() {
int num = 20;
MyClass obj(10, num); // 初始化常量和引用
obj.display();
return 0;
}
输出:
Constructor called
x: 10, ref: 20
5. 构造函数的重载
构造函数可以根据参数列表进行重载,以支持多种对象初始化方式。
#include <iostream>
using namespace std;
class MyClass {
int x, y;
public:
MyClass() : x(0), y(0) {} // 默认构造函数
MyClass(int a) : x(a), y(0) {} // 单参数构造函数
MyClass(int a, int b) : x(a), y(b) {} // 双参数构造函数
void display() {
cout << "x: " << x << ", y: " << y << endl;
}
};
int main() {
MyClass obj1;
MyClass obj2(10);
MyClass obj3(10, 20);
obj1.display();
obj2.display();
obj3.display();
return 0;
}
输出:
x: 0, y: 0
x: 10, y: 0
x: 10, y: 20
6. 构造函数的注意事项
- 不能为构造函数指定返回类型(即使是
void
)。 - 构造函数可以是
explicit
,避免隐式类型转换。 - 避免递归调用构造函数,会导致栈溢出。
总结
构造函数的主要作用是:
- 自动初始化对象。
- 提供灵活的初始化方式(如有参构造、拷贝构造、委托构造)。
- 支持成员对象、继承等复杂场景的初始化。