C++ C++;-在运行时从基类指针标识派生类
我正在试验状态机,我试图实现的状态机使用函数指针来表示状态C++ C++;-在运行时从基类指针标识派生类,c++,polymorphism,C++,Polymorphism,我正在试验状态机,我试图实现的状态机使用函数指针来表示状态 typedef void (*State)(Signal const&) class StateMachine { public: void exampleState(Signal const&); private: State m_currentState; } 基本上,我想为每个信号派生一个单独的类,在每个状态函数中,状态机必须能够确定接收到哪种信号并执行相应的代码。我想出的解决办法是 class
typedef void (*State)(Signal const&)
class StateMachine
{
public:
void exampleState(Signal const&);
private:
State m_currentState;
}
基本上,我想为每个信号派生一个单独的类,在每个状态函数中,状态机必须能够确定接收到哪种信号并执行相应的代码。我想出的解决办法是
class Signal {};
class MySignal: public Signal {};
void StateMachine::exampleState(Signal const& signal){
if (typeid(signal) == typeid(MySignal)){
//code here
}
// other cases...
}
首先,我不确定以这种方式使用typeid是否是一种好的做法。而且,只有当信号至少有一个虚函数时,这才起作用
另一种解决方案是定义一种类型标志(如枚举),并在派生信号构造函数中传递相应的类型标志
enum signalType{
mySignalType
//other types
}
class Signal {
public:
Signal(signalType sig_type):m_type(sig_type){};
const signalType m_type;
};
class MySignal: public Signal {
public:
MySignal():Signal(mySignalType){};
};
void StateMachine::exampleState(Signal const& signal){
switch (signal.m_type){
case mySignalType:
//code here
break;
// other cases...
}
}
尽管这需要在每次写入新信号类时扩展枚举
有没有更优雅的方式来实现这一点?或者是另一种完全避免这种检查的技术?我记得在其他场景中也有这个问题,这就是为什么标题中的问题比上面的示例更一般。您想要实现的目标可以通过多态性实现 在
Signal
中声明一个方法(或抽象方法),并在MySignal
中实现它:
class Signal {
public:
virtual void my_method() const = 0;
};
class MySignal: public Signal {
public:
void my_method() const override {
// do something
}
};
然后在exampleState
中调用您的方法,这将调用实现的方法:
void StateMachine::exampleState(Signal const& signal){
signal.my_method();
}
您想要实现的目标可以通过多态性实现 在
Signal
中声明一个方法(或抽象方法),并在MySignal
中实现它:
class Signal {
public:
virtual void my_method() const = 0;
};
class MySignal: public Signal {
public:
void my_method() const override {
// do something
}
};
然后在exampleState
中调用您的方法,这将调用实现的方法:
void StateMachine::exampleState(Signal const& signal){
signal.my_method();
}
使用
dynamic\u cast
代替typeid
:
class Signal {
public:
virtual ~Signal() {}
};
class MySignal: public Signal {};
void StateMachine::exampleState(Signal const& signal){
if (dynamic_cast<MySignal const *>(&signal)){
//code here
}
// other cases...
}
类信号{
公众:
虚拟~Signal(){}
};
MySignal类:公共信号{};
无效状态机::示例状态(信号常量和信号){
中频(动态广播和信号)){
//代码在这里
}
//其他情况。。。
}
使用动态\u cast
而不是类型ID
:
class Signal {
public:
virtual ~Signal() {}
};
class MySignal: public Signal {};
void StateMachine::exampleState(Signal const& signal){
if (dynamic_cast<MySignal const *>(&signal)){
//code here
}
// other cases...
}
类信号{
公众:
虚拟~Signal(){}
};
MySignal类:公共信号{};
无效状态机::示例状态(信号常量和信号){
中频(动态广播和信号)){
//代码在这里
}
//其他情况。。。
}
与信号相关的动作取决于状态。状态机中函数指针的好处在于,您不必检查当前状态。只需调用当前状态函数,它包含所有内容。使用此方法,我必须在每个my_method()
实现中使用(可能)长switch语句检查我的状态。或者我遗漏了什么?在你的exampleState
方法中,你可以根据你的状态调用不同的Signal
方法,这不是你想要的吗?例如,如果Signal
有两种方法update
和render
,则可以根据您的状态调用这些方法。但是您并不真正关心它们的实现,这取决于您如何在继承自Signal
的类中实现这些方法。例如,您可以有一个渲染立方体或渲染球体,但状态为“render”。如果我这样做,我需要在类Signal
中为每个状态声明一个方法,它基本上是StateMachine
接口的副本,并且这些方法必须在每个派生类中定义(即,如果两个信号在相同状态下需要相同的功能,我需要相同的代码两次)。除此之外,它还将状态机功能移动到信号
类,这不是我想要的。信号
仅用于通知发生了什么事情,并可能存储一些数据。与信号相关联的操作依赖于状态。状态机中函数指针的优点是t您不必检查当前状态。只需调用包含所有内容的current state函数即可。使用此方法,我必须在每个my_method()中使用(可能)长switch语句检查我的状态
实现。还是我遗漏了什么?在你的示例state
方法中,你可以根据你的状态调用一个不同的信号
方法,这不是你想要的吗?例如,如果信号
有两个方法更新
和渲染
,你会根据你的状态调用这些方法。但是你没有I don’我真的不在乎它们的实现,这取决于你如何在继承自信号的类中实现这些方法。你可以有一个渲染立方体,例如渲染球体,但状态是“render”。如果我这样做,我需要在类信号
中为每个状态声明一个方法,这基本上是一个coStateMachine
接口的py,这些方法必须在每个派生类中定义(即,如果两个信号在相同状态下需要相同的功能,我需要相同的代码两次)。除此之外,它会将状态机功能移动到信号
类,这不是我想要的。信号
只应通知发生了什么事情,并可能存储一些数据。这可能是最好的选择,尽管只有在类具有虚拟table@dr.umma应该是这样的,因为当使类的层次结构成为最好的选择时,您应该有一个虚拟析构函数,尽管只有当类有一个虚拟析构函数时,这也有效table@dr.umma它应该这样做,因为在创建类的层次结构时应该有一个虚拟析构函数