说明:委托构造函数是 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) 构造函数来初始化 nameage。这样,我们不需要在 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 类型的面积参数,它通过委托给接受长度和宽度参数的构造函数来初始化对象。另一个构造函数接受对角线长度参数,它通过计算正方形的一半对角线来初始化长度和宽度。

通过这些案例,我们可以看到委托构造函数如何帮助我们减少代码重复,并使得类的构造函数更加清晰和易于维护。这种机制特别适用于那些具有多个构造函数和复杂初始化逻辑的类。

04-06 07:52