C++ 标准特性:委托构造与继承构造


一、委托构造函数(Delegating Constructor)—— C++11

1.1 概述

委托构造函数允许当前类的某个构造函数调用同类的其他构造函数来完成初始化。这样可以避免在多个构造函数中编写重复的初始化代码。

1.2 委托构造函数与普通构造函数的区别

区别点 普通构造函数 委托构造函数
成员初始值列表 初始化成员变量 只有一个参数,即同类中另一个构造函数
函数体
执行顺序 初始化列表 → 函数体 被委托函数初始化列表 → 被委托函数函数体 → 委托构造函数函数体

关键规则:当被委托构造函数的函数体中有代码时,先执行完被委托构造函数的函数体,然后才会执行委托构造函数的函数体。

1.3 执行流程图解

委托构造函数 Test(int d)
    │
    ├→ 调用被委托构造函数 Test("default", d)
    │       ├→ 初始化列表:_data(d), _str("default")
    │       └→ 函数体:cout << "普通构造函数"
    │
    └→ 委托构造函数自身的函数体:cout << "委托构造函数"

1.4 示例代码

#include <iostream>
using namespace std;

// 创建一个类
class TestC {
public:
    // 普通构造函数
    TestC(string s, int d) :_data(d), _str(s) {
        cout << "程序执行:普通构造函数的函数体" << endl;
        cout << endl;
    }

    // 委托构造函数 ①:只传 int,string 用默认值
    TestC(int d):TestC("default", d) {
        cout << "程序执行:委托构造函数的函数体" << endl;
        cout << endl;
    }

    // 委托构造函数 ②:只传 string,int 用默认值
    TestC(string s) :TestC(s, 0) {
        cout << "程序执行:委托构造函数的函数体" << endl;
        cout << endl;
    }

    void printData() {
        cout << "------程序执行:普通成员函数的函数体------" << endl;
        cout << "数据成员_data的值为:" << _data << endl;
        cout << "数据成员_str的值为:" << _str << endl;
        cout << endl;
    }

private:
    int _data;
    string _str;
};

int main()
{
    TestC objc1("hello", 10);   // 普通构造函数
    objc1.printData();

    TestC objc2("helo", 20);    // 普通构造函数
    objc2.printData();

    TestC objc3("hello");       // 委托构造函数 → 内部调用 TestC("hello", 0)
    objc3.printData();

    return 0;
}

运行结果

1.5 调用分析

对象 构造方式 实际调用链
objc1("hello", 10) 普通构造 直接匹配 TestC(string, int)
objc2("helo", 20) 普通构造 直接匹配 TestC(string, int)
objc3("hello") 委托构造 TestC(string)TestC("hello", 0)

二、继承构造函数(Inheriting Constructor)—— C++11

2.1 概述

在 C++ 中,构造函数不能是虚函数,因此构造函数不能被继承。但从 C++11 开始,可以通过 using 关键字达到继承构造函数的效果——让派生类"借用"基类的构造函数。

2.2 原理

  • using Base::Base; —— 派生类自动获得基类的所有构造函数
  • using Base::func; —— 派生类也可以引入基类的非虚成员函数

2.3 示例代码

#include <iostream>
using namespace std;

struct A
{
    void func(double d) {
        cout << "基类A:" << d << endl << endl;
    }
};

struct B : A
{
    // C++11 标准中,利用 using 关键字,使派生类可以继承父类的成员函数
    using A::func;

    void func(int i) {
        cout << "派生类:" << i << endl;
    }
};

int main()
{
    A a;
    a.func(78);          // 调用 A::func(double)

    B b;
    b.func(87);          // 调用 B::func(int),就近匹配

    return 0;
}

运行结果

2.4 调用分析

调用 匹配函数 原因
a.func(78) A::func(double) A 只有一个 func78 隐式转为 double
b.func(87) B::func(int) B 有两份 func87 精确匹配 int 版本
b.func(87.0) A::func(double) 精确匹配 double 版本(由 using 引入)

using A::func; 将基类的 func(double) 引入派生类的作用域,与派生类自己的 func(int) 构成重载关系。

2.5 using 继承构造函数(补充)

struct Base {
    Base(int x)       { cout << "Base(int)\n"; }
    Base(int x, int y){ cout << "Base(int,int)\n"; }
};

struct Derived : Base {
    using Base::Base;  // 继承所有基类构造函数(C++11)
};

int main()
{
    Derived d1(1);       // 调用 Base(int)
    Derived d2(1, 2);    // 调用 Base(int,int)
    return 0;
}

三、对比总结

特性 委托构造 继承构造(using)
关键词 在初始化列表调用同类构造函数 using Base::Base;
作用域 同一类内部 派生类与基类之间
解决什么问题 避免多构造函数重复初始化 让派生类可直接使用基类构造函数
执行顺序 先被委托函数体 → 再委托函数体 基类构造 → 派生类构造
C++ 版本 C++11 C++11

更多推荐