C++基础(十四)继承构造函数、委派构造函数

这是C++11里的知识,如果所用的编译器不支持,直接忽视;

我用的IED:visual stadio 2019。

1、继承构造函数

构造函数非常重要,但有时候真是又爱又恨,尤其是在一些类的继承中,子类和基类的构造函数完全相同,却需要将所有基类的构造函数全部重新写一遍,非常厌烦。

C++11推出了继承构造函数的概念,对于很多继承类,无需再重复编写完全一样的构造函数。

例如,公司根据职工的能力不同分为不同等级,各个等级的基本工资和绩效工资都不一样,绩效工资与各个月的绩效系数挂钩。据此,可以设计出很简单的代码结构,如下:

#include <iostream>

class Employee
{
public:
    explicit Employee(const std::string& strName):m_strName(strName), m_dRatio(1){}
    Employee(const std::string& strName, double dRatio) :m_strName(strName), m_dRatio(dRatio) {}

    const std::string& GetName() const { return m_strName; }

    double ActualPrice() const { return GetRegularWage() + GetMeritPay() * m_dRatio; }

protected:

    /// @brief 基本工资
    virtual double GetRegularWage() const = 0;

    /// @brief 绩效工资
    virtual double GetMeritPay() const = 0;

protected:
    double m_dRatio;  //绩效系数
    std::string m_strName; //名字

};

class Grade1 : public Employee
{
public:
    using Employee::Employee;

protected:
    virtual double GetRegularWage() const override { return 5000; }
    virtual double GetMeritPay() const override { return 3000; }
};

class Grade2 : public Employee
{
public: 
    using Employee::Employee;

protected:
	virtual double GetRegularWage() const override { return 6000; }
	virtual double GetMeritPay() const override { return 4000; }
};

void PrintInfo(const  Employee& r)
{
    std::cout << r.GetName() << "的工资:" << r.ActualPrice() << "\n";
}

int main()
{
    Grade1 em1("张三");
    Grade2 em2("李四", 0.4);
    PrintInfo(em1);
    PrintInfo(em2);
    
    system("pause");
    return 0;
}

程序很简单,有一个职工的基类Employee,包含两个成员变量:名称和绩效系数。有两个重载的构造函数,一个只需要指定员工姓名,绩效默认为1;另一个需要指定姓名和绩效。

基类中有一个获取实际工资的接口,实现很简单:实际工资=基本工资+绩效工资*绩效系数。基本工资和绩效工资都是纯虚函数,由各个子类实现。

两个子类,Grade1和Grade2,表示不同的等级。这两个基类仅需要实现获取基本工资和绩效工资的虚函数即可,没有任何其他信息。如果是之前,必须要各写两个构造函数,构造函数中再调用子类的相应构造函数。用了C++11,直接写:using Employee::Employee; 即可。

main函数的对象实例化可以看出来,基类Employee的两种构造函数均被继承了下来,非常方便。

运行结果如下:

2、委派构造函数

委派构造函数,就是将某个构造函数,委派给其他的构造函数实现。

类似上面的例子,基类Employee有两个构造函数,功能很类似。仅传一个名字的构造函数,其实就是调用另一个构造函数绩效系数设为1。

修改Employee,实现如下:

class Employee
{
public:
    explicit Employee(const std::string& strName):Employee(strName, 1){}  //将实现委派给另一个构造函数
    Employee(const std::string& strName, double dRatio) :m_strName(strName), m_dRatio(dRatio) {}

    const std::string& GetName() const { return m_strName; }

    double ActualPrice() const { return GetRegularWage() + GetMeritPay() * m_dRatio; }

protected:

    /// @brief 基本工资
    virtual double GetRegularWage() const = 0;

    /// @brief 绩效工资
    virtual double GetMeritPay() const = 0;

protected:
    double m_dRatio;  //绩效系数
    std::string m_strName; //名字

};

可以看到,explicit Employee(const std::string& strName)构造函数,调用的是另一个构造函数,将系数设为1。这个调用其他构造函数实现自身的被称为委派构造函数,而被调用的构造函数被称为目标构造函数。

执行结果如下:

完全没有变化。

委派构造函数有以下几点需要注意:

1、委派构造函数不能有初始化列表;

2、目标构造函数的执行总是先于委派构造函数;

3、避免目标构造函数和委派构造函数中初始化同样的成员变量;

4、不能形成委托环。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值