私はC ++、ブースト、およびステートマシンの使用が初めてです。ポリモーフィックなboost::msmステートマシンの例を知っている人はいますか?
提供されている基本的な例で遷移アクションを仮想に変更しようとしましたが、リンカーは次のように述べています。
「DerivedClass の vtable」への未定義の参照
編集: エラーは、コードを分析することによって解決された、基本的で退屈なインクルード/定義エラーでした。
基本的な例をもう一度注意深く読んだ後、ポリモーフィックにするには、子クラスでバックエンドを定義し、フロントエンドから継承する必要があることに気付きました。
以下のソース ファイルでは、ポリモーフィックの基本的な msm が定義されています。
- 花は状態のない死んだオブジェクトです
- FlowerMSM はステート マシンです (Flower に MSM の動作を与える方法)
- LiveFlower は両方から継承し、FlowerMSM からの遷移アクションをオーバーライドします
LiveFlower.cpp
#include "Flower.hpp"
#include "FlowerMSM.hpp"
class LiveFlower: public Flower, public player_
{
void waterAction(evNoWater const&);
void stopWateringAction(evEnoughWater const&);
};
//Idle
void LiveFlower::waterAction(evNoWater const&) { std::cout << "Here goes call to LiveFlower::waterAction"; }
//Watering
void LiveFlower::stopWateringAction(evEnoughWater const&) { std::cout << "Here goes call to LiveFlower::stopWateringAction"; }
typedef msm::back::state_machine<LiveFlower> FonFon;
int main()
{
FonFon =new FonFon f();
f.start();
f.process_event(evNoWater());
}
FlowerMSM.cpp
#include <iostream>
// back-end
#include <boost/msm/back/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>
// FlowerMSM is the boost::msm state machine of Flower and defines the logic of its dynamic behavior in response to external events.
namespace msm = boost::msm;
namespace mpl = boost::mpl;
namespace
{
// events
struct evNoWater {};
struct evEnoughWater {};
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
template <class Event,class FSM>
void on_entry(Event const& ,FSM&)
{
std::cout << "entering: Flower Player" << std::endl;
}
template <class Event,class FSM>
void on_exit(Event const&,FSM& )
{
std::cout << "leaving: Flower Player" << std::endl;
}
// The list of Flower states
struct Idle : public msm::front::state<>
{
// every (optional) entry/exit methods get the event passed.
template <class Event,class FSM>
void on_entry(Event const&,FSM& ) {std::cout << "Flower entering: Idle" << std::endl;}
template <class Event,class FSM>
void on_exit(Event const&,FSM& ) {std::cout << "Flower leaving: Idle" << std::endl;}
};
struct Watering : public msm::front::state<>
{
// every (optional) entry/exit methods get the event passed.
template <class Event,class FSM>
void on_entry(Event const&,FSM& ) {std::cout << "Flower entering: Watering" << std::endl;}
template <class Event,class FSM>
void on_exit(Event const&,FSM& ) {std::cout << "Flower leaving: Watering" << std::endl;}
};
// the initial state of the Flower player SM. Must be defined
typedef Idle initial_state;
// transition actions
//Idle
virtual void waterAction(evNoWater const&) { std::cout << "Here goes call to Flower::waterAction"; }
//Watering
virtual void stopWateringAction(evEnoughWater const&) { std::cout << "Here goes call to Flower::stopWateringAction"; }
typedef player_ p; // makes transition table cleaner
// Transition table for player
struct transition_table : mpl::vector<
// Start Event Next Action Guard
// +---------+-------------+---------+---------------------+----------------------+
a_row < Idle , evNoWater , Watering , &p::waterAction >,
a_row < Watering , evEnoughWater , Idle , &p::stopWateringAction >
// +---------+-------------+---------+---------------------+----------------------+
> {};
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const& e, FSM&,int state)
{
std::cout << "no transition from state " << state
<< " on event " << typeid(e).name() << std::endl;
}
};
// Pick a back-end
typedef msm::back::state_machine<player_> FlowerMSM;
}
完全を期すために、"Dead" フラワー クラス: Flower.hpp
#include <string>
#include <iostream>
class Flower
{
public:
Flower();
Flower(std::string type);
std::string getType();
void setType(std::string type);
void water();
void stopWatering();
private:
std::string typ;
};
Flower::Flower(){}
Flower::Flower(std::string type){typ=type;}
std::string Flower::getType(){return typ;}
void Flower::setType(std::string type){typ=type;}
void Flower::water(){std::cout<<"watering now";}
void Flower::stopWatering(){std::cout<<"stopped watering ";}
編集: 誰かがより良い解決策を持ってきた場合に備えて、まだ自分の答えを受け入れていません。