2016-12-08 96 views
1

我想從基類繼承構造函數並在派生類中定義一個額外的構造函數。使用關鍵字繼承構造函數時發生意外的行爲

#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總共有三個用戶定義的構造函數。我能想到的唯一的事情是繼承的構造函數被視爲隱式聲明的默認構造函數,並且添加額外的構造函數將刪除默認的構造函數。

我已經試過這在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

IIRC,你不能繼承使用'using Base :: Base;'聲明的默認構造函數。您可以繼承所有其他構造函數。 –

+0

如果我刪除了Derived(int,int)並運行該程序,Derived d2;似乎會調用Base :: Base,儘管第二次認爲這是因爲隱式的Derived :: Derived正在調用Base: :Base'? – Izaan

+1

我認爲這是正確的。 –

回答

3

CppReference

If the using-declaration refers to a constructor of a direct base of the class being defined (e.g. using Base::Base;), constructors of that base class are inherited, according to the following rules:

1) A set of candidate inheriting constructors is composed of

[rules here]

2) All candidate inherited constructors that aren't the default constructor or the copy/move constructor and whose signatures do not match user-defined constructors in the derived class, are implicitly declared in the derived class. The default parameters are not inherited

所以你不能繼承一個默認的構造函數。當一個類聲明瞭一個用戶定義的構造函數時,編譯器不會爲該類生成一個默認構造函數,除非您明確要求使用Derived() = default。當你刪除你的用戶定義的構造函數時,編譯器可以爲你生成一個默認的構造函數。