我正在構建「系統」,以便稍後可以在「基於操作」的環境中編寫。我想要的是給我的實例(即「汽車」)一定的狀態(即停車,駕駛,起步)。那麼在某些情況下,應該根據狀態執行代碼。將常規類成員轉換爲靜態類成員
我不想使用一個開關/的if-then-else語句,因爲這是很容易出錯&難以擴展。 (爲了允許更多的狀態)。相反,我想使用函數指針。
我的代碼(忽略的功能sillyness,他們證明):
#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
enum State {Set, Add, Mul};
class car {
public:
typedef void (car::*MemFn)(int v);
car(int v, State _s) : val(v), s(_s) {
posFunctions.insert(std::make_pair(State(Set),&car::SetVal));
posFunctions.insert(std::make_pair(State(Add),&car::AddVal));
}
void DoIt(int v) {
//MemFn t = &car::SetVal;
MemFn t = posFunctions.find(s)->second;
CALL_MEMBER_FN(*this,t)(v);
}
int val;
State s;
protected:
std::map<State,car::MemFn> posFunctions;
void SetVal(int v) {
val = v;
}
void AddVal(int v) {
val += v;
}
void MulVal(int v) {
val *= v;
}
};
這個工程,我期望的那樣。 (我可以調用創建一個汽車對象,給它一個特定的狀態,然後調用「doit - 這將是該事件觸發的功能」來執行這些操作)。
然而,有1件很煩人的事情:我創建函數映射(映射與功能的狀態來執行),每節車廂的對象獨立。這實際上並不「真實」(事實上,每個汽車在狀態&事件相同時總是執行相同的操作),因此容易出錯/難看。
我試圖使「posFunctions」靜態地圖,並使用用於2線在構造的靜態初始化功能。
main.obj:錯誤LNK2001:無法解析的外部符號 「受保護:靜態類的std ::地圖,一流的std ::分配器>>汽車:: posFunctions」?(posFunctions @汽車@@ 1V $ @地圖W4State @@ P8car @@ @ AEXH ZU?$ @少@@@ W4State STD @@ V'$分配器@ U&$對@ $$ CBW4State @@ P8car @@ AEXH @ Z @ STD @@@ 4 @@性病@@ A) 我想這是因爲我訪問一個非靜態成員函數 - 即使它是指向?
是它可能使地圖靜態(或全球)?
謝謝你的幫助, paul23
你的鏈接錯誤放在一邊(其他人已經在下面回答了),你有沒有考慮使用狀態模式來建模?可能會做出更清晰的實施。 http://en.wikipedia.org/wiki/State_pattern – razlebe 2010-11-19 17:02:24
感謝大家的答案,我真的需要更加小心這些事情。 – paul23 2010-11-19 17:14:25
如果您的編譯器沒有它,請使用std :: function或boost :: function。 – 2010-11-19 17:16:45