2016-12-29 133 views
4

代碼打印所有的構造函數。我讀到構造函數在我們從另一個類派生一個類時沒有被繼承。那麼爲什麼創造cba爲什麼構造函數被調用,如果他們沒有被繼承?

class A 
{ 
public: 
    A() { cout << "A's constructor called" << endl; } 
}; 

class B 
{ 
public: 
    B() { cout << "B's constructor called" << endl; } 
}; 

class C: public B, public A // Note the order 
{ 
public: 
    C() { cout << "C's constructor called" << endl; } 
}; 

int main() 
{ 
    C c; 
    return 0; 
} 
+3

[C++超類構造函數調用規則]的可能重複(http://stackoverflow.com/questions/120876/c-superclass-constructor-calling-rules) – Soeren

回答

5

當您閱讀文件說構造函數是「不繼承」,它的意思是,如果類A定義構造函數A::A(int x),然後子類B不會自動有一個構造函數的int

但是,仍然需要初始化父類的值;否則,父對象可能處於無效狀態。構造函數用於初始化類,因此意味着一個的父類的構造函數必須從子構造函數的初始化程序列表被調用。如果父類具有默認構造函數,那麼默認情況下會調用該構造函數。這就是你在例子中看到的。如果家長不提供一個默認的構造函數,你必須指定要叫哪一個:

class A 
{ 
public: 
    A(int x) { cout << "A's constructor called" << endl; } 
}; 

class C: public A 
{ 
public: 
    C() 
    : A(7) /* compilation will fail without this line */ 
    { cout << "C's constructor called" << endl; } 
}; 
0

構造調用構造函數在傳統意義上是不能繼承的。

類是繼承的。

但是爲了構建一個類,需要調用它的構造函數。這是它的工作。硬性規則,沒有例外。

當您從第二個類繼承一個類時,構造第一個類需要構造第二個類。因爲第一類總是包含第二類。另一個硬性規則,沒有例外。這就是「繼承」的意思。

所以,構造第一個類將調用它的構造函數。然後,爲了構建第二個類,它的構造函數也需要被調用(實際上第二個類是先構造的,然後是第一個類的構造)。

這就是爲什麼兩個構造函數都會被使用。

0

構造函數當類繼承時調用。除此之外,繼承基本上給出了派生類實例的匿名基類成員實例。這些實例需要被構造,以便它們的構造函數被調用。

0

「構造函數不能被繼承」的意思,C類應,將有它自己的構造函數,儘管事實有B的構造函數,它將不能使用B的構造函數而不是C的構造函數。而這正是你得到的:你得到所有父類的構造函數。

當你有類的層次結構,並從一個構造對象時,將從基礎開始,所有他的父母將有順序構造。

當你要摧毀它們時,從他開始,他和他的所有父母將會連續遭到毀滅。

按規則:第一次創建 - 最後被破壞。

0

通過不繼承,C++ 11種標準手段本

class A 
{ 
    public: 
     A(int x) {} 
}; 

class B: public A 
{ 
}; 

int main(void) 
{ 
    B b(5); 
    return 0; 
} 

這將無法編譯因爲A(int)不被繼承。您可以定義B通過

class B: public A 
{ 
    using A::A; 
}; 

在你的情況明確地繼承A(int)您所定義的所有默認的構建函數,並明確定義與否,仍然存在,將被命名爲對象初始化的部分原因是由於您的C c宣言。

0

C++繼承基本上創建了一個由其超類的部分組成的類。例如:

class A { 
    public: 
     A() { 
      std::cout << "Constructor A" << '\n'; 
     } 
}; 

class B : public A { 
    public: 
     B() { 
      std::cout << "Constructor B" << '\n'; 
     } 
}; 

class C : public B { 
    public: 
     C() { 
      std::cout << "Constructor C" << '\n'; 
     } 
}; 

C類實際上是C類,具有B類部分和A類部分。所以爲了構造類C,我們需要通過調用這些部分的構造函數來構造它的每個部分。這些構造函數的順序是從最基類到最派生類(在本例中爲A到C)。最基礎的是繼承樹頂部的類,而最基礎的類是底部的類。

同樣的規則也適用於析構函數。唯一的區別是,destrutors從大多數派生到最基礎(C到A)。

2

我讀到,當我們從另一個類

這是正確的派生類的構造函數是不能繼承的。但是,你似乎誤解了這個意思。

比方說,你有:

struct A 
{ 
    A(int) {} 
}; 

struct B : A 
{ 
    B() : A(0) {} 
}; 

鑑於上述情況,你將無法使用:

B b(10); 

因爲A(int)不受B繼承。

這是你誤會的癥結所在。

從B那麼爲什麼的C創建正在調用構造函數和一個

然而,當你構建一個BB構造函數被調用,以初始化它的成員。還必須調用A的構造函數,以便可以初始化對應於AB的子對象。

有幾種方法可以初始化A-部分B

  1. 您可以通過使用語法使用的A構造函數中顯式成員初始化列表:

    B() : A(0) {} 
    
  2. 離開成員初始化空,在這種情況下A默認構造函數被調用。

    B() {} 
    

    這相當於:

    B() : A() {} 
    

    在我所呈現的例子中,這將導致在一個編譯錯誤因爲A默認構造已經通過提供另一個構造比所述不同刪除默認構造函數。

回來到您的落實C默認構造函數,你必須:

C() { cout << "C's constructor called" << endl; } 

這相當於

C() : B(), A() { cout << "C's constructor called" << endl; } 

B::B()A::A()被調用時的C實例被構造。

相關問題