C ++ - 在运行时从基类指针识别派生类

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C ++ - 在运行时从基类指针识别派生类相关的知识,希望对你有一定的参考价值。

我正在试验状态机,而我正在尝试实现的那个使用函数指针来表示状态

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是一种很好的做法。此外,这仅在Signal具有至少一个虚拟功能时才有效。

另一种解决方案是定义一种类型的标志,如枚举,并在派生信号构造函数中传递相应的一个

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...
  }
}

虽然这要求每次写入新的信号类时都要扩展枚举。

有更优雅的方式实现这一目标吗?或者也许是另一种可以避免这种检查的技术?我记得在其他场景中也有这个问题,这就是为什么标题中的问题比上面的例子更普遍。

答案

使用dynamic_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中实现它:

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();
}

以上是关于C ++ - 在运行时从基类指针识别派生类的主要内容,如果未能解决你的问题,请参考以下文章

从基类指针访问两个具有不同类型的派生成员变量。

从基类函数派生的类容器

如何从基类调用派生赋值运算符?

如何从基类动态创建和使用派生类?

c ++设计:从基类转换为派生类,没有额外的数据成员

如何从基类调用派生类函数?