2014-03-24 76 views
-3

我寫了下面的代碼,我不明白爲什麼Enemy()構造函數被調用兩次。另外,作爲一個側面問題,我想問一下,是否通過使成員函數變爲虛擬並重新編寫定義來重寫成員函數是覆蓋類之間函數的「正確」方式。被調用兩次的類構造函數

#include <iostream> 
using namespace std; 

class Enemy { 
    public: Enemy(); 
    virtual void attack(); 
}; 

Enemy::Enemy() { 
    cout << "\nEnemy created"; 

} 

void Enemy::attack() { 
    cout << "\nattack inflicts 10 damage"; 

} 

class Boss: public Enemy { 
    public: Boss(); 
    virtual void attack(); 
}; 

Boss::Boss() { 
    cout << "\nYou encounter a boss"; 
} 
void Boss::attack() { 
    cout << "\nattack inflicts 30 damage"; 
} 

int main() { 
    Enemy enemy1; 
    enemy1.attack(); 
    Boss boss1; 
    boss1.attack(); 
    return 0; 
} 
+6

你正在創造兩個敵人 - 一個也恰好是一個老闆。所以爲每個敵人調用構造函數。 –

+0

我讀到,costructors不會繼承繼承。這裏發生了什麼? – 101

+0

不確定你的意思是「不要超越」,但如果你的意思是基類構造函數仍然會被調用,那麼是的,那就是發生了什麼。它也具有邏輯意義 - 你還能如何初始化基類中的私有成員? –

回答

5

我不明白爲什麼敵()構造函數被調用兩次

因爲它繼承了它,BossEnemy類型。當你構造一個Boss時,調用BossEnemy的構造函數。

// Redacted lines that aren't important. 
Enemy enemy1; 
Boss boss1; 

以上兩行有效地創建了兩個Enemy類型的實例。其中一個恰好不僅僅是一個Enemy,它是一個Boss。但它仍然是Enemy,因此對這兩個對象都調用Enemy的構造函數。

我想問一下重寫成員函數是否通過使它們變爲虛擬然後再次編寫它們的定義是覆蓋類之間函數的「正確」方式。

是的。

+0

我明白了。那麼我們如何解決這個問題呢?不要兩次調用Enemy構造函數? – 101

+0

你不能!一個'老闆'是'敵人'! – 2014-03-24 20:58:38

+1

這不是問題。在這種特殊情況下,'Enemy'只有一個方法,所以調用它的構造函數似乎是多餘的。但是,想象一下'Enemy'具有諸如'int hitpoints'等字段的情況。這個字段必須被初始化。如果「Boss」的構造不會調用「Enemy」的構造函數,那麼「Boss」會有未定義的生命值。 –

1

自您Enemy衍生Boss,一個BossEnemy。你可以認爲這是Boss裏面有一個隱形的Enemy成員,所以當你創建一個Boss時,它的構造函數調用Enemy來初始化這個「不可見」成員。

關於你的第二個問題:是的,但不要忘記使用關鍵字override註釋此。

0

老闆是敵人的孩子。所以Enemy的構造函數在純Boss的構造函數之前被調用。

Boss::Boss() : Enemy() 
{ 
    cout << "\nYou encounter a boss"; 
} 
相關問題