C++ 访问抽象 class 指针向量的 subclass 的成员

C++ accessing member of subclass of abstract class pointer vector

此处错误:

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

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

您需要添加

virtual float getThrust() = 0;

在你的 RocketPart class 中。 此外,我认为完全没有理由使用虚拟继承(仅当您从多个 classes and 继承时才需要使用 The Diamond Problem),所以改为:

class Engine : virtual public RocketPart {

你应该没问题:

class Engine : public RocketPart {

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

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

class RocketPart {
public:
    RocketPart();
    RocketPart(const RocketPart& orig);
    virtual ~RocketPart();

    virtual float getThrust();

    virtual void print() = 0;
protected:
    // some members
};

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

rocket[0]->getThrust();

你需要写:

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

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

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

  • virtual float getThrust() 添加到您的 RocketPart class。这可能不是一个好的解决方案,因为并非所有 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(); } }

您将无法施放任何 RocketPart* 不是 Engine

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

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

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