我正在创建一个状态机,它允许您将状态添加到堆栈中。以下是其中包含的几种方法:
void pushState(State* state);
State* getCurrentState();
State
只是一个基类,用于创建派生类。因此,我创建了一个名为GameState
的派生类,它具有一个称为foo
的独特方法。如果我执行以下操作,则它将不允许我访问foo
,因为“对于State类,不存在名为'foo'的方法。
State* currentState = myStateMachine.getCurrentState();
我还尝试将State*
更改为GameState*
,但由于getCurrentState()
返回类型State
,因此无法正常工作。当我实际上不知道当前状态是什么派生状态时,如何获取堆栈中的当前状态?
我也不知道为什么它允许我将GameState
压入期望State
的堆栈中,但不允许我以GameState
的身份检索它。相反,它使我可以在State
上检索它。
答案 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
。]