【问题标题】:Inherited Constructors in C++C++ 中的继承构造函数
【发布时间】:2017-08-09 01:37:36
【问题描述】:

我正在尝试在 C++ 中练习继承构造函数。我已经在 gcc 中编译并运行了以下程序,它工作正常。

#include<iostream>
using namespace std;

class Base1
{
public:
        Base1()
        {
                cout<<"Base1 Default Constructor\n";
        }
        Base1(int i)
        {
                cout<<"Base1 parametrized Constructor\n";
        }
};

class Base2
{
public:
        Base2()
        {
                cout<<"Base2 Default Constructor\n";
        }
        Base2(const string& s)
        {
                cout<<"Base2 parametrized Constructor\n";
        }
};

class Derived :public Base1, public Base2
{
public:
        using Base1::Base1;
        using Base2::Base2;
};

int main()
{
        Derived d1(3);        // OK 
        Derived d2("hello");  // OK 
}

输出:

Base1 parametrized Constructor
Base2 Default Constructor
Base1 Default Constructor
Base2 parametrized Constructor

但是,我想知道,为什么要调用默认构造函数?

【问题讨论】:

    标签: c++ c++11 inheritance constructor


    【解决方案1】:

    调用默认构造函数是因为Derived 继承自Base1Base2。当您构造 Derived 对象时,需要构造这两个基础。所以当你这样做时

    Derived d1(3);
    

    您致电Base1(int i)。现在您需要构造 Base2 部分,由于您没有指定如何构造它,编译器默认构造它。同样的事情发生在

    Derived d2("hello");
    

    由于您没有指定如何在构造函数中构造Base1 部分,编译器默认为您构造它。然后调用Base2(const string&amp; s) 构造Base2 部分。

    基本上你所拥有的是

    class Derived :public Base1, public Base2
    {
    public:
            Derived(int n) : Base1(n), Base2() {}
            Derived(const std::string& str) : Base1(), Base2(str) {}
    };
    

    【讨论】:

      【解决方案2】:

      来自 cppreference http://en.cppreference.com/w/cpp/language/using_declaration
      如果 using 声明引用了正在定义的类的直接基类的构造函数(例如 using Base::Base;),则根据以下规则继承该基类的构造函数:

      1) 一组候选继承构造函数由
      组成 a) 基类的所有非模板构造函数(省略省略号参数后,如果有)(C++14 起)
      b) 对于每个带有默认参数或省略号参数的构造函数,所有通过删除省略号并从参数列表末尾省略默认参数而形成的所有构造函数签名一一
      c) 基类的所有构造函数模板(省略省略号参数后,如果有)(C++14 起)
      d) 对于每个带有默认参数或省略号的构造函数模板,通过删除省略号并从参数列表末尾省略默认参数而形成的所有构造函数签名一一列出
      2) 不是默认构造函数或复制/移动构造函数并且其签名与派生类中用户定义的构造函数不匹配的所有候选继承构造函数,都在派生类中隐式声明。不继承默认参数:

      struct B1 {
          B1(int);
      };
      struct D1 : B1 {
          using B1::B1;
      // The set of candidate inherited constructors is 
      // 1. B1(const B1&)
      // 2. B1(B1&&)
      // 3. B1(int)
      
      // D1 has the following constructors:
      // 1. D1()
      // 2. D1(const D1&) 
      // 3. D1(D1&&)
      // 4. D1(int) <- inherited
      };
      
      struct B2 {
          B2(int = 13, int = 42);
      };
      struct D2 : B2 {
          using B2::B2;
      // The set of candidate inherited constructors is
      // 1. B2(const B2&)
      // 2. B2(B2&&)
      // 3. B2(int = 13, int = 42)
      // 4. B2(int = 13)
      // 5. B2()
      
      // D2 has the following constructors:
      // 1. D2()
      // 2. D2(const D2&)
      // 3. D2(D2&&)
      // 4. D2(int, int) <- inherited
      // 5. D2(int) <- inherited
      };
      

      继承的构造函数等效于用户定义的构造函数,其主体为空,成员初始化列表由单个嵌套名称说明符组成,它将所有参数转发给基类构造函数。

      它与相应的基本构造函数具有相同的访问权限。如果用户定义的构造函数满足 constexpr 构造函数要求,则为 constexpr。如果相应的基构造函数被删除,或者如果一个默认的默认构造函数将被删除,它就会被删除(除了构造函数被继承的基的构造不计算在内)。继承构造函数不能显式实例化或显式特化。

      如果两个 using 声明继承了具有相同签名的构造函数(来自两个直接基类),则程序是非良构的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-01-21
        • 2015-06-09
        • 2018-06-28
        • 1970-01-01
        • 1970-01-01
        • 2020-04-22
        • 2012-11-14
        • 1970-01-01
        相关资源
        最近更新 更多