C++ 新特性委托构造和继承构造

#include <iostream>
#include <vector>
#include <list>
/** 委托构造函数作用时调用其他构造函数(目标构造函数)进行初始化,优点是优化代码,看起来精简
 *  在初始化列表中调用构造函数,函数体中调用构造函数会报参数重复定义问题
 *  目标构造函数执行优先与委托构造函数
 */

struct Test
{
    Test(){}; 
    Test(int max)   // 目标构造函数
    {
        this->m_max = max;
    }
    Test(int max, int min) : Test(max)  // 即是委托构造函数,也是目标构造函数
    {
        this->m_min = max > min ? min : 1;
    }
    Test(int max, int min, int mid) : Test(max, min) // 委托构造函数
    {
        this->m_mid = mid > min && mid < max ? mid : 50;
    }

    int m_max;
    int m_min;
    int m_mid;
};

/*
 在初始化列表中使用委托构造函数初始化类成员变量后,不能在初始化列表中再次初始化这个成员变量了
Test(int max, int min):Test(max), m_max(max) // error
 */

class Base
{
public:
    Base(int i) : m_i(i) {}
    Base(int i, double j) : m_i(i), m_j(j) {}
    Base(int i, double j, std::string k) : m_i(i), m_j(j), m_k(k) {}

    void Func(int i)
    {
        std::cout << "Base:"<< i << std::endl;
    }

    void Func(int i, int j)
    {
        std::cout <<"Base:"<< i << "," << j << std::endl;
    }
	void Func1(int i, int j, int k)
	{
		std::cout<< "Base:"<< i << "," << j << "," << k << std::endl;
	}
    int m_i;
    double m_j;
    std::string m_k;
};

// 在C++11之前,子类初始化父类成员,都是在子类构造函数初始化列表中初始化父类成员变量,比较繁琐
class Child : public Base
{
public:
    // 如父类构造函数只有有参构造函数时(有无参默认构造函数,不需要再初始化列表中初始化父类),必须在初始化列表中初始化父类成员变量
    Child(int l, int i) : m_l(l), Base(i) {}
    Child(int l, int i, double j) : m_l(l), Base(i, j) {}
    Child(int l, int i, double j, std::string k) : m_l(l), Base(i, j, k) {}
    int m_l;
};

class Child1 : public Base
{
public:
    // 在子类中可以调用父类的所有构造函数
    using Base::Base;

    // C++11之前可以使用using父类的函数
    using Base::Func;
    void Func()
    {
        std::cout << "child1 Func" << std::endl;
    }
};


void Test1()
{
    // using Base constructor
    Child1 c1(1);   
    std::cout << c1.m_i << std::endl;// 1
    Child1 c2(2, 3);
    std::cout << c2.m_i << "," << c2.m_j << std::endl;// 2,3
    Child1 c3(3, 4, "5");
    std::cout << c3.m_i << "," << c3.m_j << "," << c3.m_k << std::endl;// 3,4,5

    // using Base function
    c1.Func(); // child1 Func
    c1.Func(1); // Base:1
    c1.Func(1, 2);// Base:1,2
    c1.Func1(1, 2, 3);// Base:1,2,3


    // 一般调用父类函数,就是使用父类的对象引用或指针
}

// 若子类中也有自己成员需要初始化,又要使用继承构造函数,则可以
// 用=、{}对子类成员进行就地初始化(C++11开始支持)
struct Child2: public Base
{
    using Base::Base;
    int c=0;
    std::string str{"c++"};
};

void Test2()
{
    Child2 child(1);
    std::cout<<child.c<<","<<child.str<<std::endl; // 0,c++
}

// 委托构造函数注意不能形成环状,否则编译报错
struct DelegateConstruction {
    //DelegateConstruction():DelegateConstruction(1){}
    //DelegateConstruction(int a):DelegateConstruction("b"){}
    //DelegateConstruction(char b):DelegateConstruction(2){}

    int a;
    char b;
};


// 委托构造函数一个很实际应用是创建一个模板构造函数作为目标构造函数
// 通过委托构造函数的委托,构造函数模板被实例化,比罗列不同类型构造函数方便多
// 委托构造函数使得构造函数的泛型编程成为可能
struct DelegateTemplate{
    template<typename T>
    DelegateTemplate(T begin, T end):l(begin, end){} // 模板构造函数作为目标构造函数

    std::vector<int> l;

    DelegateTemplate(std::vector<int> &vec):DelegateTemplate(vec.begin(), vec.end()){}// 委托构造函数
    DelegateTemplate(std::list<int> &l):DelegateTemplate(l.begin(), l.end()){}  // 委托构造函数
};

// 委托构造函数可以捕获到目标构造函数中抛出的异常
struct DelegateException{
    DelegateException():a(1){throw 1;}

    DelegateException(char b) try: DelegateException(){
            this->b = b;
            std::cout<<"a:"<<a<<",b:"<<b<<std::endl; // 目标构造函数抛出异常,委托构造函数体并没有执行
        }catch(int e){
            std::cout<<"except:"<<e<<std::endl; // 1
        }
    
    int a;
    char b;
};
void Test3()
{
    DelegateException d('d');
}
int main()
{
    Test test(5, 1, 3);
    std::cout << test.m_max << "," << test.m_mid << "," << test.m_min << std::endl; // 5,3,1
    Test1();
    Test2();
    Test3();
    return 0;
}
<think>好的,我现在需要详细回答用户关于C++委托构造函数继承构造函数的概念、语法及使用场景的问题。首先,我需要回顾一下用户提供的引用内容,确保信息准确。 首先看委托构造函数。根据引用[1],委托构造函数是C++11引入的特性,允许一个构造函数调用同类的另一个构造函数,这样可以减少重复代码。引用[2]中的代码示例显示,比如MyClass的默认构造函数委托给了带int参数的构造函数。引用[3]提到,委托构造函数主要用于解决多个构造函数中存在重复初始化代码的问题,提升代码复用性。 然后是继承构造函数。引用[4]展示了两种方式,一种是基类有默认构造函数,派生类通过using声明继承;另一种是派生类自定义构造函数并调用基类构造函数。这里需要注意,继承构造函数允许派生类直接使用基类的构造函数,而不必重新编写。 接下来需要整理两者的概念、语法使用场景。对于委托构造函数,语法是在成员初始化列表调用同类其他构造函数。使用场景是当多个构造函数有共同的初始化步骤时,避免代码重复。例如,多个构造函数都需要初始化某些成员变量,可以将其提取到一个目标构造函数中,其他构造函数委托它执行。 而继承构造函数则是通过using声明将基类构造函数引入派生类,这样派生类可以直接使用基类的构造函数。这在派生类不需要添加额外初始化逻辑时非常有用,简化代码。但需要注意,如果基类有多个构造函数,派生类使用using声明后,也会继承所有基类构造函数。但如果有派生类自己的成员需要初始化,可能需要额外处理。 需要对比两者的区别:委托构造函数是在同一个类中委托,而继承构造函数是派生类继承基类的构造函数。使用场景不同,一个是类内部构造函数复用,另一个是派生类复用基类构造逻辑。 另外,用户可能存在的疑问是,这两种构造函数如何结合使用?例如,在派生类中,是否可以同时使用委托构造函数继承构造函数?比如,派生类先继承基类的构造函数,然后在自己定义的构造函数中委托其他构造函数。这应该是可行的,但需要注意构造函数的执行顺序初始化列表的正确性。 还需要注意潜在的问题。例如,委托构造函数不能形成循环委托,否则会导致未定义行为。继承构造函数如果基类构造函数有参数,派生类可能需要处理这些参数,特别是在有默认参数的情况下。 最后,总结两者的优势:委托构造函数减少同类中的重复代码,继承构造函数简化派生类的构造过程,避免重复编写基类已有的构造函数。</think>### C++委托构造函数与继承构造函数详解 #### 一、委托构造函数 1. **概念** 委托构造函数是C++11引入的特性,允许同一类中的某个构造函数(委托构造函数)调用另一个构造函数(目标构造函数)完成初始化。委托构造函数会将控制权先交给目标构造函数,待其执行完毕后再执行自身的主体逻辑[^1][^3]。 2. **语法** ```cpp class MyClass { public: MyClass(int value) : value_(value) {} // 目标构造函数 MyClass() : MyClass(0) {} // 委托构造函数 private: int value_; }; ``` 通过**成员初始化列表调用目标构造函数**,且不能与其他初始化操作共存[^2]。 3. **使用场景** - 多个构造函数存在重复初始化代码时,提取公共逻辑到目标构造函数中。 - 简化重载构造函数的实现,例如默认参数构造委托特定参数构造[^3]。 4. **注意事项** - 禁止循环委托(如A委托B,B又委托A)。 - 目标构造函数需先于委托构造函数定义。 --- #### 二、继承构造函数 1. **概念** 继承构造函数(C++11特性)允许派生类通过`using`声明直接继承基类的构造函数,无需重复编写基类已有的构造函数[^4]。 2. **语法** ```cpp struct Base { Base(int a) { /*...*/ } }; struct Derived : Base { using Base::Base; // 继承Base的所有构造函数 }; ``` 派生类可额外添加成员初始化: ```cpp struct Derived : Base { using Base::Base; int derived_member = 0; // 直接初始化 }; ``` 3. **使用场景** - 派生类无需修改基类构造逻辑时,直接复用基类构造函数。 - 基类有多个重载构造函数时,避免逐个重写。 4. **注意事项** - 若派生类需要初始化自身成员,需结合成员默认初始化或委托构造函数。 - 基类构造函数参数需与派生类兼容。 --- #### 三、对比与典型应用 | 特性 | 委托构造函数 | 继承构造函数 | |------------------|----------------------------------|----------------------------------| | **作用对象** | 同一类内的构造函数 | 基类与派生类之间的构造函数 | | **核心目的** | 减少同类构造函数间的重复代码 | 复用基类构造逻辑 | | **语法关键词** | 成员初始化列表调用同类构造函数 | `using Base::Base` | | **典型场景** | 多个构造函数共享初始化步骤 | 派生类直接沿用基类构造函数 | --- #### 四、结合使用示例 ```cpp class Animal { public: Animal(int age) : age_(age) {} Animal() : Animal(0) {} // 委托构造函数 private: int age_; }; class Cat : public Animal { public: using Animal::Animal; // 继承构造函数 Cat() : Animal(), name_("Unknown") {} // 委托+继承组合 private: std::string name_; }; ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值