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”。如果我这样做,我需要在类
信号
中为每个状态声明一个方法,这基本上是一个co
StateMachine
接口的py,这些方法必须在每个派生类中定义(即,如果两个信号在相同状态下需要相同的功能,我需要相同的代码两次)。除此之外,它会将状态机功能移动到
信号
类,这不是我想要的。
信号
只应通知发生了什么事情,并可能存储一些数据。这可能是最好的选择,尽管只有在类具有虚拟table@dr.umma应该是这样的,因为当使类的层次结构成为最好的选择时,您应该有一个虚拟析构函数,尽管只有当类有一个虚拟析构函数时,这也有效table@dr.umma它应该这样做,因为在创建类的层次结构时应该有一个虚拟析构函数