接口的解决方法

时间:2011-10-18 14:37:24

标签: c++ inheritance interface

在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;
}

2 个答案:

答案 0 :(得分:5)

首先,您必须(或至少希望)将构成您的界面的功能公开:

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

然后你将继承它(C ++没有“接口”和“类”作为单独的概念)。

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

最后,由于这些是多态类型,你需要创建一个指向敌人的指针集合,而不是实际的Enemy对象:

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

这确实引发了对象生存期和所有权问题(这些问题主要不是Java中的问题)。当你将一个项目添加到集合中时,你需要确保它不会被破坏,只要你打算使用它,并且一旦你完成它就会被销毁(例如,当一个敌人被击败时,你可能想删除它)。您需要决定EnemyManager是否要删除不再需要的敌人或其他一些代码。如果EnemyManager要删除它们,您可能需要(或想要)将一个clone函数添加到您的Enemy界面,以便获取要添加到集合中的对象的副本。

编辑:根据您的评论,您不太确定如何使用您存储在集合中的指针的敌人“界面”。幸运的是,这很简单,就像这样:

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

答案 1 :(得分: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
}