c++继承与抽象函数实现

C++ inheritance and abstract function implementation

本文关键字:实现 抽象函数 继承 c++      更新时间:2023-10-16

我得到cannot instantiate abstract class错误。现在我意识到了这一点的含义,但是我不知道我的代码是怎么做错的。所以我在这里,寻求帮助。

Action.h:

#ifndef ACTION_H
#define ACTION_H
// ===== Dependencies ===== //
#include ...
... 
// ===== Classes ===== //
class Action
{
public:
    Action();
    void set(...);
    virtual void doAction() = 0;
};
#endif

MoveAction.h:

#ifndef MOVE_ACTION_H
#define MOVE_ACTION_H
// ===== Dependencies ===== //
#include ...
...
// ===== Classes ===== //
class MoveAction : public Action
{
public:
    MoveAction(...); // Constructor 
    using Action::set;
    void doAction(); // Do action
private:
    ...
};
#endif

MoveAction.cpp:

#include "MoveAction.h"
MoveAction::MoveAction(...) : Action() {
    ...
}
/* Do action */
void MoveAction::doAction() {
    ...
    setTile(...);
}

所以本质上我是在继承Action.hMoveAction.h类中实现doAction()。但是,当我执行以下操作时:

Actor.cpp:

...
vector<Action> Actor::getActions(...) {
    vector<Action> actions = vector<Action>();
    actions.push_back(MoveAction(...));
    ...
    return actions;
}

我使用Action的向量,所以未来的动作类型(例如AttackAction)可以添加到这个向量中,我所需要做的就是调用action.doAction()来执行动作。然而,这样做给了我cannot instantiate abstract class错误…

如果我把代码改成:

...
vector<MoveAction> Actor::getActions(...) {
    vector<MoveAction> actions = vector<MoveAction>();
    actions.push_back(MoveAction(...));
    ...
    return actions;
}

它工作得很好(注意将所有类型更改为MoveAction),但这显然会阻止任何可扩展性选项。

有人有什么想法吗?我觉得我错过了一些很明显的东西。

谢谢!

不能有类型为Action的对象向量,即:

vector<Action>

因为抽象类不能有实例。然而,你可以有一个指向抽象类的指针向量。

vector<Action*>

这样多态行为将被保留。注意:存储Action而不是Action*将是一个错误,即使它不是编译错误,因为您将面临切片。还要记住,在处理原始指针时要正确处理内存管理。您可以使用某种句柄来指针,这将缓解内存问题:std::shared_ptr, boost::shared_ptr或类似的。这样你就会引入一点效率开销,但只要你是初学者,这是强烈建议的。不要担心这个,因为这可能是预优化。首先,你需要一个正确的,工作的代码,不泄漏内存,然后你可以随时调整(优化)。

c++标准n3337 § 10.4/1抽象类
抽象类机制支持一般概念的概念,如形状,其中只有比较具体的变体,如圆形正方形,可以用。也可以使用抽象类定义一个接口,派生类为其提供各种实现。

c++标准n3337 § 10.4/2

抽象类是只能作为类的基类使用的类其他类;不能创建抽象类的对象除非作为派生类的子对象。类是抽象的如果它至少有一个纯虚函数。【注:这样的函数。可能是继承的:见下文。- end note]虚函数为通过在函数中使用pure-specifier(9.2)指定pure类定义中的声明。(…)

下面是如何使用std::vector<std::unique_ptr<Action>>代替std:vector<Action>的示例:

#include <iostream>
#include <vector>
#include <memory>
class Action {
 public:
  typedef std::vector<std::unique_ptr<Action>> Ptrs;
  Action() { }
  virtual void doAction() = 0;
};
class MoveAction : public Action {
 public:
  MoveAction() { }
  void doAction() { std::cout << "MoveAction::doAction" << std::endl;}
};
class Actor {
 public:
  Action::Ptrs getActions();
};
Action::Ptrs
Actor::getActions() {
  Action::Ptrs actions;
  actions.emplace_back(new MoveAction());
  return actions;
}
int main() {
  Actor actor;
  Action::Ptrs actions = actor.getActions();
  actions.back()->doAction();
}