如果将派生类的方法作为基类返回,该如何访问派生类的方法?

时间:2019-02-07 02:46:15

标签: c++ class oop

我正在创建一个状态机,它允许您将状态添加到堆栈中。以下是其中包含的几种方法:

void pushState(State* state);

State* getCurrentState();

State只是一个基类,用于创建派生类。因此,我创建了一个名为GameState的派生类,它具有一个称为foo的独特方法。如果我执行以下操作,则它将不允许我访问foo,因为“对于State类,不存在名为'foo'的方法。

State* currentState = myStateMachine.getCurrentState();

我还尝试将State*更改为GameState*,但由于getCurrentState()返回类型State,因此无法正常工作。当我实际上不知道当前状态是什么派生状态时,如何获取堆栈中的当前状态?

我也不知道为什么它允许我将GameState压入期望State的堆栈中,但不允许我以GameState的身份检索它。相反,它使我可以在State上检索它。

2 个答案:

答案 0 :(得分:0)

您应该将State *类型转换为GameState *

我的意思是:

State* currentState = myStateMachine.getCurrentState();

应该是

// if State class don't have any virtual method, you should use static_cast<>
GameState* currentState = static_cast<GameState*>(myStateMachine.getCurrentState());

// if State class has at least virtual method, you should use dynamic_cast<>
GameState* currentState = dynamic_cast<GameState*>(myStateMachine.getCurrentState());

它将起作用

答案 1 :(得分:0)

尝试一下:

#include <iostream>

namespace {
    class State {
    public:
        virtual int foo() const = 0;
    };
    class GameState : public State {
    public:
        int foo() const { return 5; }
    };
}

int main() {
    const GameState s{};
    std::cout << s.foo() << "\n";
    const State *const p = &s;
    std::cout << p->foo() << "\n";
    return 0;
}

要用GameState替换C ++中foo()的方法State,该方法必须是虚拟的。原因是,默认情况下,出于效率考虑,C ++编译器会在编译时计算foo()的地址。 virtual关键字通过指向结构的指针间接指向地址,该结构列出了GameState类型的虚拟方法。

您的问题是,除非foo()是虚拟的,否则您的计算机无法在运行时告诉State *对象是指向State对象还是指向{{1} }对象。

但是,如果GameState是虚拟的,则每个包含foo()对象的State对象都包含一个指向隐藏的 vtable的指针。 {{1 }} 类型有一个 vtable。 GameState类型有另一个 vtable。每个 vtable 都引用适当的功能State

[示例中的GameState会通知编译器不会为foo()对象提供适当的实际功能= 0。您可以在代码中省略foo(),而根据需要提供State。]