C ++继承和抽象函数实现

时间:2014-05-21 17:05:13

标签: c++ inheritance polymorphism virtual abstract

我收到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(...);
}

基本上我在继承doAction()的班级MoveAction.h中实施Action.h。但是,当我执行以下操作时:

Actor.cpp

...
vector<Action> Actor::getActions(...) {
    vector<Action> actions = vector<Action>();

    actions.push_back(MoveAction(...));
    ...

    return actions;
}

我使用了Action的向量,因此可以将未来的Action类型(例如AttackAction)添加到此向量中,我需要做的就是调用action.doAction()来执行它那个行动。但是,执行上述操作会给我cannot instantiate abstract class错误..

如果我将代码更改为:

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

    actions.push_back(MoveAction(...));
    ...

    return actions;
}

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

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

谢谢!

2 个答案:

答案 0 :(得分:6)

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

vector<Action>

因为抽象类不能有实例。但是,您可以使用指向抽象类的指针。

vector<Action*>

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

C ++标准版n3337 § 10.4 / 1抽象类

  

抽象类机制支持一般概念的概念,   如形状,其中只有更具体的变体,如圆形   和方,实际上可以使用。也可以使用抽象类   定义派生类提供各种各样的接口   的实施方式。

C ++标准版n3337 § 10.4 / 2

  

抽象类是一个只能用作基类的类   其他一些班级; 无法创建抽象类的对象   除了作为从它派生的类的子对象。一堂课是抽象的   如果它至少有一个纯虚函数。 [注意:这样的功能   可能是遗传的:见下文。 - 结束语]虚拟功能是   通过在函数中使用纯说明符(9.2)来指定pure   类定义中的声明。 (...)

答案 1 :(得分:0)

以下是如何使用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();
}