gpt4 book ai didi

c++ - 有没有办法调用模板参数类的未知方法?

转载 作者:太空狗 更新时间:2023-10-29 23:05:29 24 4
gpt4 key购买 nike

我曾经实现过这样的状态机:

class Player
{
public:
int Run();
int Jump();
int Stop();

private:
class State
{
public:
virtual int Run() = 0;
virtual int Jump() = 0;
virtual int Stop() = 0;
};

class StandingState : public State
{
virtual int Run() { /*...*/ }
virtual int Jump() { /*...*/ }
virtual int Stop() { /*...*/ }
};

class RunningState : public State
{
virtual int Run() { /*...*/ }
virtual int Jump() { /*...*/ }
virtual int Stop() { /*...*/ }
};

// More states go here!

std::list<State*> states;
State* currentState;
};

int Player::Run()
{
int result = m_currentState->Run();

// do something with result
}

int Player::Jump()
{
int result = m_currentState->Jump();

// do something with result
}

int Player::Stop()
{
int result = m_currentState->Stop();

// do something with result
}

我认为这完全是一本教科书:Player 将来自外部的调用委托(delegate)给它当前的 State 对象,并对结果做一些事情(可能转换到另一个状态)。从本质上讲,每个状态都知道给定的 Action 如何影响它,但要由状态机将各种状态连接在一起。我发现这是一个很好的关注点分离。

但我在这里看到了抽象的可能性。整个系统由State类的接口(interface)定义:

  1. 状态机和子状态都实现了State
  2. 状态机保留指向所有可能的State 和当前State
  3. 的指针
  4. 无论在状态机上调用 State 的什么方法,它都会被无差别地转发到当前状态。

所以,我们完全可以把它变成一个类模板,对吧?看:

template< class StateInterface >
class StateMachine : public StateInterface
{
// public methods already declared in StateInterface

protected:
std::list<StateInterface*> states;
void AddState(StateInterface* state);
StateInterface* currentState;
};

class PlayerStateInterface
{
public:
virtual int Run() = 0;
virtual int Jump() = 0;
virtual int Stop() = 0;
};

class Player : public StateMachine< PlayerStateInterface >
{
public:
virtual int Run() { currentState->Run(); /* do stuff */ }
virtual int Jump() { currentState->Jump(); /* do stuff */ }
virtual int Stop() { currentState->Stop(); /* do stuff */ }
};

在以上几点中,第 1 点和第 2 点已经涵盖,但是第 3 点呢?我仍然必须在具体的状态机实现中手动将调用委托(delegate)给当前状态。有没有办法将该功能移动到 StateMachine 模板?我能否以某种方式表示,每当 StateMachine 上调用 StateInterface 的方法时,它应该在 currentState 上调用相同的方法,而我不知道StateInterface 方法的名称或签名?

最佳答案

如果您正在寻找针对 RunJumpStop 具有不同签名的情况的一般答案,我不会不知道有没有好的解决办法。但是,在您的示例中,它们都具有相同的签名,这向我表明以下方法可能有效:

#include <iostream>

class AbstractState
{
public:
virtual void write1() = 0;
virtual void write2() = 0;
};

class State1: public AbstractState
{
public:
virtual void write1() { std::cout << "1-1" << std::endl; }
virtual void write2() { std::cout << "1-2" << std::endl; }
};

class State2: public AbstractState
{
public:
virtual void write1() { std::cout << "2-1" << std::endl; }
virtual void write2() { std::cout << "2-2" << std::endl; }
};

template <typename StateInterface>
class Player
{
public:
Player(StateInterface *s_):
s(s_)
{
}

void setState(StateInterface *s_)
{
s = s_;
}

void execute(void (StateInterface::*method)())
{
(s->*method)();
}
private:
StateInterface *s;
};

int main()
{
State1 s1;
State2 s2;

Player<AbstractState> p(&s1);

p.execute(&AbstractState::write1);
p.execute(&AbstractState::write2);

p.setState(&s2);

p.execute(&AbstractState::write1);
p.execute(&AbstractState::write2);

return 0;
}

我能够使用 GCC 4.5.2 编译和运行它并得到预期的结果,即:

1-1
1-2
2-1
2-2

正如我所说,我不确定是否有一种好的方法可以将其扩展到 AbstractState 的不同成员函数采用不同的参数或返回不同的值的情况,并且可能还有其他我还没有考虑到的缺点。它不像我认为您希望找到的那样好,但希望这至少可以作为一个好的起点。

关于c++ - 有没有办法调用模板参数类的未知方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19188422/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com