我解決了我的問題。這裏是很好簡潔的代碼。 該信號也是一個模板類,它簡單地定義了它可能發出的消息類型。 因此,當將信號連接到一個插槽時,Link構造函數可以檢查信號發出的消息類型和插槽接受的消息類型的多態兼容性。然後它複製相應的函數指針,無論是否需要動態強制轉換。這裏沒有顯示的是Type類以及它如何用來檢查消息類型的兼容性。
答案是如何定義兩個插槽函數及其函數指針。
下面是一個例子如何槽將在類定義:
class MyAction : public Action
{
public:
//! Define shared pointer on object
typedef std::shared_ptr<MyAction> Ptr;
//! Constructor
MyAction(const std::string& name)
: Action(name),
m_slotMsgM(this),
m_slotMsgA(this),
m_slotMsgB(this)
{
}
//! Register the slots with their name for dynamic linking
void configure()
{
add("processMsgM", &m_slotMsgM);
add("processMsgA", &m_slotMsgA);
add("processMsgB", &m_slotMsgB);
}
//! Slot method
void processMsgM(Message::Ptr msg, Link * link = nullptr)
{
cout << "MyAction::processMsgM: Msg " << msg->type().name() << endl;
}
//! Slot method
void processMsgA(MsgA::Ptr msg, Link * link = nullptr)
{
cout << "MyAction::processMsgA: Msg " << msg->type().name() << endl;
}
//! Slot method
void processMsgB(MsgB::Ptr msg, Link * link = nullptr)
{
cout << "MyAction::processMsgB: Msg " << msg->type().name() << endl;
}
protected:
//! Define slots
SlotT<MyAction, Message, &MyAction::processMsgM> m_slotMsgM;
SlotT<MyAction, MsgA, &MyAction::processMsgA> m_slotMsgA;
SlotT<MyAction, MsgB, &MyAction::processMsgB> m_slotMsgB;
};
這裏是時隙和SLOTT類定義。
class Link;
typedef std::set<Link*> LinkSet;
//! Base class for Slot template class
class Slot
{
friend class Link;
public:
//! Slot function pointer
typedef std::function<void (Message::Ptr, Link*)> Function;
//! Disconnect all links
~Slot();
//! Return the type of message accepted by this Slot function
const TypeDef& messageType() const { return m_msgType; }
//! Return slot function applying a dynamic cast on the message pointer
Function getDynamicCastFunction() const
{ return m_dynamicCastFunction; }
//! Return slot function applying a static cast on the message pointer
Function getStaticCastFunction() const
{ return m_staticCastFunction; }
//! Operator() using the dynamic cast
void operator()(Message::Ptr msg, Link * link = nullptr)
{ m_dynamicCastFunction(msg, link); }
protected:
//! Construct Slot by derived class instance construction only
Slot(const TypeDef& type, Function dynamicCastFunction,
Function staticCastFunction) :
m_msgType(type),
m_dynamicCastFunction(dynamicCastFunction),
m_staticCastFunction(staticCastFunction)
{
}
//! Insert link in set
void connect(Link* link)
{ m_links.insert(link); }
//! Remove link from set
void disconnect(Link* link)
{ m_links.erase(link); }
//! Set of active links
LinkSet m_links;
//! Type of accepted messages
const TypeDef& m_msgType;
//! Slot method usind dynamic cast on message pointer
const Function m_dynamicCastFunction;
//! Slot method using static cast on message pointer
const Function m_staticCastFunction;
};
template <class TObj, class TMsg,
void (TObj::*TMethod)(typename TMsg::Ptr, Link*)>
class SlotT : public Slot
{
public:
//! SlotT constructor with templated type
SlotT(TObj* obj)
: Slot(TMsg::Type(),
std::bind(&SlotT<TObj,TMsg,TMethod>::dynamicCastFunction, obj,
std::placeholders::_1,
std::placeholders::_2),
std::bind(&SlotT<TObj,TMsg,TMethod>::staticCastFunction, obj,
std::placeholders::_1,
std::placeholders::_2))
{
}
private:
//! dynamic cast function
static void dynamicCastFunction(TObj* obj,
typename Message::Ptr msg,
Link* link)
{
typename TMsg::Ptr m = std::dynamic_pointer_cast<TMsg>(msg);
if(m && obj)
(obj->*TMethod)(m, link);
}
//! static cast function
static void staticCastFunction(TObj* obj,
typename Message::Ptr msg,
Link* link)
{
typename TMsg::Ptr m = std::static_pointer_cast<TMsg>(msg);
if(m && obj)
(obj->*TMethod)(m, link);
}
};
請問爲什麼你絕對想要擺脫'dynamic_cast <>'s? – ereOn
我想這是一個表現的事情。但是,無論如何,我都有點難以理解爲什麼它是必需的。你能提供一個代碼示例來展示你的意思嗎? – Stefan
對於這種用例,它聽起來像你應該使用虛擬功能而不是動態轉換。 – Ben