C++ OOP 面试高频知识点 - 03
构造函数(无参、有参、拷贝构造、移动构造、委托构造)
1. 构造函数的基本概念
构造函数(Constructor) 是在创建对象时自动调用的特殊成员函数,它用于初始化对象的成员变量。构造函数的名称必须与类名完全相同,且不能有返回类型(包括 void)。
class MyClass {
public:
MyClass() {
// 构造函数实现
cout << "Constructor called!" << endl;
}
};
2. 构造函数的类型
2.1 无参构造函数
无参构造函数是指没有参数的构造函数。如果类中没有定义任何构造函数,编译器会自动生成一个默认的无参构造函数。
class MyClass {
public:
MyClass() {
// 无参构造函数
x = 0;
y = 0;
}
private:
int x, y;
};
int main() {
MyClass obj; // 调用无参构造函数
return 0;
}
2.2 有参构造函数
有参构造函数可以接受参数,用于初始化对象的成员变量。
class Point {
public:
Point(int x, int y) {
this->x = x;
this->y = y;
}
private:
int x, y;
};
int main() {
Point p(10, 20); // 调用有参构造函数
return 0;
}
2.3 拷贝构造函数
拷贝构造函数用于创建一个新对象,其初始值来自另一个已存在的对象。
class MyClass {
public:
MyClass(const MyClass& other) {
// 拷贝构造函数
this->x = other.x;
this->y = other.y;
}
private:
int x, y;
};
int main() {
MyClass obj1(10, 20);
MyClass obj2(obj1); // 调用拷贝构造函数
return 0;
}
2.4 移动构造函数
移动构造函数用于将资源从一个对象转移到另一个对象,避免了不必要的拷贝。
class MyClass {
public:
MyClass(MyClass&& other) noexcept {
// 移动构造函数
this->data = other.data;
other.data = nullptr;
}
private:
int* data;
};
2.5 委托构造函数
委托构造函数允许一个构造函数调用另一个构造函数,避免了代码重复。
class MyClass {
public:
MyClass() : MyClass(0, 0) { // 委托给有参构造函数
cout << "Default constructor" << endl;
}
MyClass(int x, int y) {
this->x = x;
this->y = y;
cout << "Parameterized constructor" << endl;
}
private:
int x, y;
};
3. 构造函数的特殊特性
3.1 默认构造函数
如果类中没有定义任何构造函数,编译器会自动生成一个默认构造函数。如果定义了其他构造函数,编译器不会自动生成默认构造函数。
class MyClass {
public:
MyClass(int x) { // 定义了有参构造函数
this->x = x;
}
private:
int x;
};
int main() {
// MyClass obj; // 错误:无默认构造函数
MyClass obj(10); // 正确
return 0;
}
3.2 初始化列表
使用初始化列表可以更高效地初始化成员变量,避免了默认初始化和赋值操作。
class Point {
public:
// 使用初始化列表
Point(int x, int y) : x(x), y(y) {
// 构造函数体
}
private:
int x, y;
};
3.3 explicit 关键字
使用 explicit 关键字可以防止隐式类型转换。
class MyClass {
public:
explicit MyClass(int x) {
this->x = x;
}
private:
int x;
};
int main() {
MyClass obj = 10; // 错误:不能隐式转换
MyClass obj(10); // 正确
return 0;
}
4. 常见问题和回答
问题 1:构造函数为什么没有返回类型?
构造函数的目的是初始化对象,而不是返回值。如果有返回类型,会导致语法歧义。
问题 2:什么是拷贝构造函数?什么时候会被调用?
拷贝构造函数用于创建一个新对象,其初始值来自另一个已存在的对象。当对象作为参数传递、作为返回值返回或使用 = 初始化时会被调用。
问题 3:为什么需要移动构造函数?
移动构造函数可以避免不必要的拷贝操作,提高程序效率,特别是在处理大型对象时。
总结
构造函数是 C++ 类中非常重要的成员函数,它负责在创建对象时初始化成员变量。C++ 提供了多种类型的构造函数,包括无参、有参、拷贝、移动和委托构造函数,以满足不同的需求。
练习建议:
1. 设计一个 Date 类,包含年、月、日成员变量
2. 实现无参、有参、拷贝构造和移动构造函数
3. 使用初始化列表初始化成员变量