2017-03-17 185 views
2

我正在嘗試使用C++繼承構造函數。我編譯並在gcc中運行以下程序,並且工作正常。C++中的繼承構造函數

#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 

但是,我想知道,爲什麼叫默認構造函數?

回答

5

默認構造函數被調用,因爲Derived繼承自Base1Base2。當你構造一個對象時,這兩個基地都需要構建。所以,當你做

Derived d1(3); 

你叫Base1(int i)。現在您需要構建Base2部分,並且由於您未指定方式,編譯器默認會構造它。同樣的事情發生在

Derived d2("hello"); 

既然你不指定如何構建編譯器的默認構造爲你構造的Base1部分。然後調用Base2(const string& s)構造Base2部分。

基本上你有什麼是

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

從cppreference http://en.cppreference.com/w/cpp/language/using_declaration
如果使用聲明指所定義的類的直接基的構造(例如,使用基本::基地),構造根據以下規則繼承該基類:

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。如果刪除相應的基礎構造函數或者刪除默認的默認構造函數(除了構造函數被繼承的基礎的構造不計算在外),它將被刪除。繼承構造函數不能顯式實例化或明確專用。

如果兩個使用聲明繼承具有相同簽名的構造函數(來自兩個直接基類),則該程序不合格。