有没有办法调用模板参数类的未知方法
Is there any way to call unknown methods of a template argument class?
我曾经实现过这样的状态机:
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
将来自外部的调用委托给其当前State
对象,并对结果执行某些操作(可能过渡到另一种状态(。从本质上讲,每个状态都知道给定的操作如何影响它,但由状态机将各种状态连接在一起。我发现这是一个很好的关注点分离。
但我在这里看到了抽象的可能性。整个系统由State
类的接口定义:
- 状态
- 机和子状态都实现
State
- 状态机保留一个指向所有可能的
State
和当前State
的指针 - 无论在状态机上调用什么
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 呢?我仍然必须在具体的状态机实现中手动将调用委托给当前状态。有没有办法将该功能移动到StateMachine
模板?我是否可以以某种方式表达,每当调用StateInterface
方法时StateMachine
当我不知道StateInterface
方法的名称或签名时,它应该在currentState
上调用相同的方法?
如果您正在寻找Run
、Jump
和Stop
具有不同签名的情况的一般答案,我不知道是否有一个好的解决方案。但是,在您的示例中,它们都具有相同的签名,这向我表明以下方法可能有效:
#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
的不同成员函数采用不同参数或返回不同值的情况,并且可能还有其他我尚未考虑的缺点。它并不像我认为您希望找到的那么好,但希望这至少可以作为一个良好的起点。
相关文章:
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- QtQuick - qml:28:错误:未知方法返回类型:自定义类型
- 如何在C++中循环访问未知对象方法?
- 通过模板函数对未知类型调用方法
- qml 未知方法返回类型:ArchiveFile*,即使调用了 qmlRegisterUncreatableType
- 运行 QML 时出现"未知方法参数类型"错误
- 在C++结构中处理未知类型的最佳方法是什么?
- 当类型未知时调用模板方法
- C 通过未知名的变量到方法
- 未知的方法语法
- C++将int转换为具有未知基的字符串的简单方法
- 填充未知大小的 std::vector 的最快方法
- 解决方法:未知此类主机
- 未知类方法回调,它接受 0 个参数并返回可转换为 int 的类型
- 将未知大小的整数转换为其无符号形式的最短/最干净方法
- 有没有办法调用模板参数类的未知方法
- C++中具有多态模板类的未知方法返回类型
- 处理未知容器中所有项目的最有效方法
- 以未知的顺序执行函数的最有效方法