2012-03-23 72 views
1

我對C++非常陌生,非常感謝任何和所有的幫助。我有這個任務可以玩類和繼承。我的理解是,我可以在基類中編寫一個虛擬函數,它被繼承類中的相同名稱的函數覆蓋。當我調用任何繼承類時,這種方法很好,但是當我將它們插入一個寫入基類的函數中時,即使它接收的對象來自繼承類,它也會從繼承類調用初始化器,但其他只能從基類中運行。這裏是我的代碼縮短版本:C++如何確保何時使用虛擬繼承,它稱之爲繼承而不是基函數

基類:

#ifndef PLAYER_CPP 
#define PLAYER_CPP 
class Player 
{  
protected: 
    string playerThrow; 
public: 
    //function that sets player throw 
    void virtual setMove(); 
    string performMove() {return(playerThrow);} 
}; 
#endif 

繼承類:

class Avalanche: virtual public Player 
{ 
public: 
    Avalanche();  
    //set specific move for class 
    void setMove() 
    { 
     //always plays rock 
     playerThrow = "rock"; 
    } 
}; 

//initializer, inherit from player, set new name 
Avalanche::Avalanche() : Player() 
{ 
    //initialize name string 
    string newName; 
    //set name 
    newName = "Avalanche Player"; 
    //sets name in player class 
    name = newName; 
} 

如何我試圖使用它:

class Tournament 
{ 
public: 
    Tournament(); 
    Player bout(Player, Player); 
    Player Tournament::bout (Player p1, Player p2) 
    { 
     p1.setMove(); 
     p2.setMove(); 
     return p1; 
    } 
}; 

什麼這樣做的結果是將這一舉措設置爲無效,而不是「搖擺」。

預先感謝任何正確方向的指針。這個讓我難住。

-Victoria

+1

參見:http://stackoverflow.com/questions/274626/what-is-the-slicing -problem-in-c – Mankarse 2012-03-23 12:17:22

+2

爲什麼使用虛擬測試?我看不到虛擬繼承的任何需要 – softghost 2012-03-23 12:49:18

+0

'bout'的定義應該在類之外。符合編譯器會拒絕這個實現。 – 2012-03-23 15:36:41

回答

3

不能使用動態與複製傳遞的參數結合。您必須通過引用(Player&)或const引用(Player const&)或指針(Player*)或指向const(Player const*)的指針。

例如:如果你初始化Avalanche並將它傳遞的東西,收到Player,出現這種情況:

C++看到的是得到一個Player簽名,所以它會創建一個本地拷貝你的對象,使用帶簽名的默認拷貝構造函數:Player::Player(Player const&)。這可以被稱爲你的Avalanche論點,因爲它是繼承公開Player。嘗試隱藏Player的複製構造函數,以瞭解發生了什麼。

請隨時指出那些對你來說不理解的事情。

+1

'Player const *'不是一個常量指針,它是一個指向const Player的指針。 – 2012-03-23 12:19:32

+0

@LuchianGrigore:它總是語言的細節。謝謝,修復它... – bitmask 2012-03-23 12:24:50

+0

恆常不是一個細節。這很重要。 – 2012-03-23 12:26:55

0

您正在將Player對象傳遞給bout,因此您沒有充分利用多態性。

你應該通過指針或引用:

Player bout(Player*, Player*); 
//or 
Player bout(Player&, Player&); 

注意,在你的版本,如果你通過Avalanche對象的方法,你會碰到物體切片(看,最多)。

+1

只有當他們可以'nullptr'。如果不是,引用是更好的。 – 2012-03-23 12:20:18

+0

@CatPlusPlus權利,我編輯。 – 2012-03-23 12:21:15

+0

感謝您在對象切片上的提示,我確實遇到了這個問題。 – quipish 2012-03-23 13:14:33

0

當您致電Tournament::bout時,將從傳入的Avalanche對象中構造兩個新的Player對象。

構造函數Player不知道它正在複製/移動的對象的Avalanche部分,因此只複製Player部分。

p1p2Player S,所以他們像Player S,不Avalanche秒。

如果你不想來構建新的Player對象,然後按引用傳遞參數:

Player& Tournament::bout (Player& p1, Player& p2) 
{ 
    p1.setMove(); 
    p2.setMove(); 
    return p1; 
}