2011-10-18 155 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