2011-10-18 74 views
0

在C++中,如何聲明接口s.t.我可以使用它,如下圖所示:接口的解決方法

/** Enemy "Interface" */ 
Class Enemy { 
    Enemy(); 
    virtual ~Enemy(); 
    virtual void doStuff() = 0; 
}; 

/** Enemy of type 1 */ 
Class Enemy_type1 : public Enemy { 
    Enemy_type1(); 
    virtual ~Enemy_type1(); 
    virtual void doStuff() { 
     // different for every type of enemy 
    } 
}; 

/** Add an enemy to EnemyManager */ 
void EnemyManager::addEnemy(Enemy * e) { 
    this->enemies.push_back(*e); // declared as vector<Enemy> enemies; 
} 
+1

@see http://stackoverflow.com/questions/318064/how-do-you-declare-an-interface-in-c – Nicoretti

+0

@ Kerrek SB我加了':public enene'並改變了「c」。感謝您的提醒,一旦我找到答案,我會接受答案,因爲我經常一次處理多個問題。 – Ben

+0

@Nicoretti我不明白這是如何解決我的問題,因爲它沒有說我如何可以參考「接口」(請參閱​​我的addEnemy函數)。 – Ben

回答

5

首先,你必須(或至少希望)作出彌補你的界面公開功能:

class Enemy { 
public: 
    Enemy(); 
    virtual ~Enemy(); 
    virtual void doStuff() = 0; 
}; 

,那麼你就從它繼承(C++沒有「接口」和「類」作爲單獨的概念)。

class Emeny_type1 : public Enemy { 
    // ... 
}; 

最後,因爲這些是多態的類型,你需要創建一個指針集合的敵人,而不是實際的敵人對象:

void EnemyManager::addEnemy(Enemy const *e) { 
    enemies.push_back(e); 
} 

這確實引起對象生命週期的問題,所有權(在Java中大多數不是問題)。當你向集合中添加一件物品時,只要你打算使用它,就需要確保它不會被破壞,並且一旦你完成了它就會被銷燬(例如,當一個敵人被擊敗,你可能想要刪除它)。您需要決定EnemyManager是否要刪除不再需要的敵人或其他代碼。如果EnemyManager是要刪除它們,您可能需要(或希望)一個clone功能添加到您的敵人接口,它讓被添加到集合中的對象的副本。

編輯:基於您的評論,你不太知道如何使用您儲存在您的收藏指針的敵人「接口」。幸運的是,這是相當簡單的,像這樣:

for (int i=0; i<enemies.size(); i++) 
    enemies[i]->doStuff(); 
+0

在我看到他按價值存儲'敵人'之前,我讀了4次這個問題。 –

+0

Ohhh ...我必須寫'vector 敵人;'。看,我一直在嘗試的是'vector *敵人;' – Ben

+0

你不想(也不能)有一個'vector ' - 它需要是'vector '(並且,如示例中所示上面的代碼,你要推一個'e',不'* e'。 –

0
/* Enemy Interface (Abstract Base Class) 
    This goes in a header, say Enemy.hpp 
*/ 
class Enemy { 
public: // note default access is private in classes 
    Enemy(); 
    virtual ~Enemy(); 
    virtual void doStuff() = 0; 
}; 

/* Add an enemy to EnemyManager. 
    The interface is a type, and is known! 
    It doesn't need to know anything about the subclasses 
    which implement the interface. 
*/ 
void EnemyManager::addEnemy(Enemy * e) { 
    this->enemies.push_back(*e); // vector of Enemy POINTERS 
} 

/* Enemy of type 1. 
    This would go in say Enemy1.hpp - it depends on Enemy.hpp, 
    but EnemyManager doesn't need to know anything about this. 
*/ 
Class Enemy_type1: public Enemy { 
public: 
    Enemy_type1(); 
    virtual ~Enemy_type1(); 
    virtual void doStuff(); 
}; 

/* ... and in a .cpp file somewhere ... */ 
Enemy_type1::Enemy_type1() : Enemy() 
{ 
    // this is redundant unless you have some work for it to do 
} 

Enemy_type1::~Enemy_type1() 
{ 
} 

void Enemy_type1::doStuff() 
{ 
    // do your stuff here 
} 
+0

謝謝你,但我會用傑裏棺材的解決方案去,因爲我現在明白了它,它不會產生任何錯誤。 – Ben

+0

這仍然推回敵人b y值,儘管評論。 –

+0

你說得對,我只是把'那塊代碼'去掉了,忘了去掉這個解除引用。 – Useless