【问题标题】:C++ inheritance and abstract function implementationC++继承和抽象函数实现
【发布时间】:2014-07-10 11:27:28
【问题描述】:

我收到了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.h 的类MoveAction.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),但这显然会停止任何可扩展性选项。

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

谢谢!

【问题讨论】:

    标签: c++ inheritance polymorphism virtual abstract


    【解决方案1】:

    您不能拥有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) 指定纯 类定义中的声明。 (...)

    【讨论】:

    • 您的意思是:存储“Action”而不是“Action*”吗?
    • Action 而不是MoveAction ;)
    • @Mr_Hic-up 存储 Action 而不是 Action* 即使可以编译也会出错
    • 啊!就是这样,绝对错过了这里的明显内容。谢谢哥们!
    • @Ubobo 先生,我随时为您服务
    【解决方案2】:

    以下是如何使用std::vector&lt;std::unique_ptr&lt;Action&gt;&gt; 代替std:vector&lt;Action&gt; 的示例:

    #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();
    }
    

    【讨论】:

      猜你喜欢
      • 2015-02-23
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      相关资源
      最近更新 更多