将常规类成员转换为静态类成员

问题描述:

我正在构建“系统”,以便稍后可以在“基于操作”的环境中编写。我想要的是给我的实例(即“汽车”)一定的状态(即停车,驾驶,起步)。那么在某些情况下,应该根据状态执行代码。将常规类成员转换为静态类成员

我不想使用一个开关/的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

+0

你的链接错误放在一边(其他人已经在下面回答了),你有没有考虑使用状态模式来建模?可能会做出更清晰的实施。 http://en.wikipedia.org/wiki/State_pattern – razlebe 2010-11-19 17:02:24

+0

感谢大家的答案,我真的需要更加小心这些事情。 – paul23 2010-11-19 17:14:25

+0

如果您的编译器没有它,请使用std :: function或boost :: function。 – 2010-11-19 17:16:45

这是可能的 - 你必须在1处(本类最有可能的CPP文件)定义静态变量。

std::map<State,car::MemFn> car::posFunctions; 

你在头文件中有哪些仅仅是一个声明

这类似于你必须提供一个功能定义在每个.cpp文件的方式工作,你在头声明。如果你错过了任何函数体,连接器将会在每个缺少的函数上给出相同的错误。

要初始化按需这种结构,(如果需要在一个线程安全的方式)提供被从你的类构造函数,但检查称为静态成员函数,不管它是被称为前。

void car::initFunctions() 
{ 
    static bool done(false); 
    if (done) 
    return; 

    // first pass, set up the map 
    done = true; 
} 

只要你宣布你map静态的,你需要添加下面一行在您的实现文件:

std::map<State,car::MemFn> car::posFunctions;

下面是相关C++ FAQ项的链接。

+0

这刚刚为我解决了一个令人讨厌的编译错误,+1谢谢 – Freddie 2011-08-04 12:56:13

你忘了在地图上定义一个全球范围内,即

std::map<State,car::MemFn> car::posFunctions;

在您定义的车.cpp文件

一般来说,当你做出这样的结构时,问问自己 - 你可以用多态性来代替吗?