说明:委托构造函数是 C++11 引入的一种特殊类型的构造函数,它通过调用同一个类中的另一个构造函数来初始化对象。这种构造函数在声明时使用 :
符号后跟其他构造函数的初始化列表,而不是在函数体内调用。委托构造函数的主要目的是避免代码重复,并简化多个构造函数之间的共同初始化逻辑。以下是一个简单的委托构造函数的示例:
class MyClass {
public:
// 基本构造函数,接受两个参数
MyClass(int a, double b) : a_(a), b_(b) {
// 初始化成员变量 a_ 和 b_
}
// 重点:委托构造函数,使用一个参数初始化
MyClass(int a) : MyClass(a, 0.0) {
// 这里没有额外的初始化代码,因为它委托给另一个构造函数
}
// 另一个重载的构造函数,接受三个参数
MyClass(int a, double b, std::string c) : a_(a), b_(b), c_(std::move(c)) {
// 初始化成员变量 a_, b_ 和 c_
}
private:
int a_;
double b_;
std::string c_;
};
注意:这里所谓的性能提升本质上是减少了成员变量初始化的时间,在一些大型工程中,成员变量初始化往往是很大的,因此要做这样的优化。
1 为什么C++11 引入委托构造函数?
C++11 引入委托构造函数的原因主要包括以下几点:
- 减少代码重复:委托构造函数允许一个构造函数调用同一个类中的另一个构造函数,这样可以避免在多个构造函数之间重复相同的初始化代码。
- 提高代码清晰度:通过委托构造函数,可以将类的构造逻辑分解成更小的、更易于管理的部分,使得代码结构更加清晰。
- 增强类的可维护性:当需要修改或扩展类的初始化逻辑时,委托构造函数使得只需在一个地方进行更改,而不是在多个构造函数中重复修改。
- 支持类的灵活设计:委托构造函数提供了一种机制,使得派生类可以重用基类的构造函数,或者在派生类中重用其他构造函数的初始化逻辑。
- 简化构造函数的重载:当类有多个构造函数时,委托构造函数可以简化这些构造函数的实现,特别是当某些构造函数共享相同的初始化步骤时。
- 优化编译器的实现:编译器可以更有效地处理委托构造函数,可能会生成更优化的代码,尤其是在处理复杂的构造函数重载和模板类时。
- 提高资源利用效率:委托构造函数可以减少不必要的资源分配和释放,尤其是在处理大型对象或资源密集型对象时,可以提高程序的执行效率。
- 支持构造函数的继承:在多重继承的情况下,委托构造函数可以使得派生类继承并利用基类的构造函数,而无需手动复制初始化代码。
通过引入委托构造函数,C++11 提供了一种更加高效和灵活的方式来设计和实现类的构造逻辑,有助于提高代码的质量和可维护性。
2 委托构造函数使用详解
委托构造函数在 C++11 中的使用案例主要体现在简化类的构造函数实现,避免代码重复,特别是在处理具有多个构造函数的类时。以下是一些包含代码实现的案例。
2.1 基础委托构造函数
参考代码如下:
class MyClass {
public:
// 默认构造函数
MyClass() :MyClass(0) {}
// 带参数的构造函数
MyClass(int importantData) : importantData(importantData) {}
private:
int importantData;
};
在这个案例中,MyClass
有两个构造函数,一个是默认构造函数,一个是接受一个 int
类型的参数。第一个构造函数通过委托给第二个构造函数来初始化 importantData
。
2.2 多重委托构造函数
参考代码如下:
class Person {
public:
// 默认构造函数
Person() : name("Unknown"), age(0) {}
// 带名字的构造函数
Person(const std::string& name) : name(name), age(0) {}
// 带名字和年龄的构造函数
Person(const std::string& name, int age)
: name(name), age(age) {
// 这里没有额外的初始化代码,因为它委托给带名字的构造函数
}
// 带年龄的构造函数,委托给带名字和年龄的构造函数
Person(int age) : Person("Unknown", age) {}
private:
std::string name;
int age;
};
在这个案例中,Person
类有多个构造函数。Person(int age)
构造函数通过委托给 Person(const std::string& name, int age)
构造函数来初始化 name
和 age
。这样,我们不需要在 Person(int age)
构造函数中重复初始化 name
的代码。
2.3 使用委托构造函数简化复杂的类设计
参考代码如下:
class Rectangle {
public:
// 构造函数,接受长和宽
Rectangle(double length, double width) : length_(length), width_(width) {}
// 委托构造函数,使用面积初始化长和宽
Rectangle(double area) : Rectangle(sqrt(area), sqrt(area)) {}
// 委托构造函数,使用正方形的对角线长度初始化
Rectangle(double diagonal) : Rectangle(diagonal / sqrt(2), diagonal / sqrt(2)) {}
private:
double length_;
double width_;
};
在这个案例中,Rectangle
类有多个构造函数。其中一个构造函数接受 double
类型的面积参数,它通过委托给接受长度和宽度参数的构造函数来初始化对象。另一个构造函数接受对角线长度参数,它通过计算正方形的一半对角线来初始化长度和宽度。
通过这些案例,我们可以看到委托构造函数如何帮助我们减少代码重复,并使得类的构造函数更加清晰和易于维护。这种机制特别适用于那些具有多个构造函数和复杂初始化逻辑的类。