使用using关键字继承构造函数时出现意外行为

时间:2016-12-08 18:02:47

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

我尝试从基类继承构造函数,并在派生类中定义一个额外的构造函数。

#include <iostream>

#define BREAK_THIS_CODE 1

class Base
{
public:
    Base()
    {
        std::cout << "Base " << "\n";
    }

    Base(int i)
    {
        std::cout << "Base " << i << "\n";
    }
};

class Derived : public Base
{
public:
    using Base::Base;

#if BREAK_THIS_CODE
    Derived(int i, int j)
    {
        std::cout << "Derived " << i << " " << j << "\n";
    }
#endif
};

int main()
{
    Derived d1(10);
    Derived d2; // error C2512: 'Derived': no appropriate default constructor available

    return 0;
}

添加Derived(int, int)似乎删除了Base(),但Base(int)不受此影响。为什么删除默认构造函数?我希望Derived总共有三个用户定义的构造函数。我唯一能想到的是继承的Base()构造函数被视为隐式声明的默认构造函数,添加额外的构造函数正在删除默认构造函数。

我在VS2015上试过这个并收到以下错误:

1>  main.cpp
1>main.cpp(37): error C2512: 'Derived': no appropriate default constructor available
1>  main.cpp(19): note: see declaration of 'Derived'

还在Coliru上尝试了这个例子:http://coliru.stacked-crooked.com/a/790b540c44dccb9f

clang++ -std=c++11 -O3 -pedantic -pthread main.cpp && ./a.out
main.cpp:35:10: error: no matching constructor for initialization of 'Derived'
        Derived d2;
                ^
main.cpp:22:14: note: candidate constructor (inherited) not viable: requires 1 argument, but 0 were provided
        using Base::Base;
                    ^
main.cpp:13:2: note: inherited from here
        Base(int i)
        ^
main.cpp:19:7: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided
class Derived : public Base
      ^
main.cpp:19:7: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided
main.cpp:25:2: note: candidate constructor not viable: requires 2 arguments, but 0 were provided
        Derived(int i, int j)
        ^
1 error generated.

1 个答案:

答案 0 :(得分:3)

CppReference

  

如果 using-declaration 引用了正在定义的类的直接基础的构造函数(例如,使用Base::Base;),则继承该基类的构造函数,具体如下规则:

     

1)一组候选继承构造函数由

组成      

[规则]

     

2)所有候选继承的构造函数不是默认构造函数或复制/移动构造函数,并且其签名与派生类中的用户定义构造函数不匹配,是隐式声明的派生类。默认参数不是继承的

因此您无法继承默认构造函数。当类声明了用户定义的构造函数时,编译器不会为该类生成默认构造函数,除非您明确要求使用Derived() = default。当您删除用户定义的构造函数时,编译器可以为您生成默认构造函数。