接口的解决方案

Workaround for Interface

本文关键字:解决方案 接口      更新时间:2023-10-16

在c++中,如何声明一个接口呢?我可以像下面这样使用它:

/** 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;
}

首先,您必须(或者至少想要)将组成接口的函数设置为公共的:

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

然后你将继承它(c++没有将"接口"answers"类"作为单独的概念)。

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

最后,因为这些是多态类型,你会想要创建一个指向敌人的指针集合,而不是真正的敌人对象:

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

这确实引发了对象生命周期和所有权的问题(这在Java中大多不是问题)。当你将道具添加到集合中时,你需要确保它在你使用它的时候不会被破坏,并且在你使用它的时候就会被破坏(例如,当敌人被击败时,你可能想要移除它)。你需要决定EnemyManager是否会删除不再需要的敌人,或者其他代码。如果EnemyManager要删除它们,你可能需要(或想要)在你的Enemy接口上添加一个clone函数,以便它获得被添加到集合中的对象的副本。

编辑:根据你的评论,你不太确定如何使用你存储在集合中的指针的敌人"接口"。幸运的是,这相当简单,就像这样:

for (int i=0; i<enemies.size(); i++)
    enemies[i]->doStuff();
/* 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
}