【问题标题】:C++ accessing member of subclass of abstract class pointer vectorC++访问抽象类指针向量子类的成员
【发布时间】:2015-07-28 14:55:35
【问题描述】:

这里出错了:

Rocket.cpp:31:16: error: no member named 'getThrust' in 'RocketPart'
    rocket[0]->getThrust();

当我想通过 vector<RocketPart*> rocketrocket[i]->getThrust() 从类 Engine 访问 getThrust() 时,我从问题顶部收到错误消息。 我究竟做错了什么?是否可以通过rocket[index]->getThrust() 访问它?

【问题讨论】:

    标签: c++ class vector polymorphism abstract


    【解决方案1】:

    RocketPart 类内部没有函数getThrust(),这就是调用该函数的向量不起作用的原因。如果getThrust() 是一个将在继承自它的类中使用的通用例程,则应将其作为虚函数添加到基类中,如下所示:

    class RocketPart {
    public:
        RocketPart();
        RocketPart(const RocketPart& orig);
        virtual ~RocketPart();
    
        virtual float getThrust();
    
        virtual void print() = 0;
    protected:
        // some members
    };
    

    【讨论】:

      【解决方案2】:

      您收到的错误是正确的:RocketPart 类中没有名为getThrust 的函数。您可以:

      • virtual float getThrust() 添加到您的RocketPart 类。这可能不是一个好的解决方案,因为并非所有RocketPart 都可以包含推力;但是,您可以简单地从中 return 0,或将其设为纯虚函数(这意味着您将不再创建 RocketPart 对象
      • dynamic_cast 将您的 RocketPart 对象转换为 Engine。这可以通过以下方式完成:

        for (size_t r = 0; r < rocket.size(); ++r) { if (const Engine* engine = dynamic_cast<Engine*>(rocket[r])) { // able to successfully convert this RocketPart into an Engine engine.getThrust(); } }

      您将无法投射任何不是EngineRocketPart*

      【讨论】:

      • 我可以使用 Rocket.addPart() 方法轻松添加 Engine* 引擎吗?还是我必须将其转换回 RocketPart* ?
      • 是的,你可以!因为EngineRocketPart 的派生类,所以任何接受RocketPart 的函数都可以传入Engine。这意味着您也可以将push_backEngine 转换为std::vector&lt;RocketPart*&gt;
      • 感谢您和其他所有人帮助我!
      【解决方案3】:

      这是因为容器中存储的类型是RocketPart。 您需要向下转换指向 Engine 的指针。 所以而不是

      rocket[0]->getThrust();
      

      你需要写:

      Engine *pPart = (Engine *) rocket[i]; //you can use also static_cast<> or dynamic_cast<>
      pPart->getThrust();
      

      使用 cast 时要小心:如果 Rocket[i] 不是引擎,程序可能会崩溃。

      【讨论】:

        【解决方案4】:

        你需要添加

        virtual float getThrust() = 0;
        

        在您的RocketPart 课程中。 此外,我认为绝对没有理由使用虚拟继承(仅当您从多个类继承并且您有The Diamond Problem 时才需要),所以改为:

        class Engine : virtual public RocketPart {
        

        你应该没问题:

        class Engine : public RocketPart {
        

        我还建议查看您的内存分配 - 如果您的示例源代码不仅仅是一个示例(您正在泄漏 Engine 对象,也许 vector&lt;shared_ptr&lt;Engine&gt;&gt; 会更好想法?)

        【讨论】:

          【解决方案5】:

          getThrust() 方法是在Engine 类中定义的,而不是在RocketPart 中。 您需要移动基类 RocketPart 中的方法,以便通过向量访问它。 或者,您也可以使用动态转换将 RocketPart“转换”为引擎。

          Engine* engine = dynamic_cast<Engine>(rocket[index]);
          if (engine) {
              engine->getThrust();
          }
          

          考虑到使用 dynamic_cast 通常意味着糟糕的设计。

          【讨论】:

            猜你喜欢
            • 2011-05-24
            • 2013-01-27
            • 1970-01-01
            • 1970-01-01
            • 2011-02-03
            • 1970-01-01
            • 2016-05-03
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多