平時寫程序時,總少不了對某個被分裝的很好的類中的成員變量進行訪問,所以會寫一些:
? void T::setXxx(Yyy v) {}
? Yyy?T::getXxx() const
這樣的代碼,因為T類中有個Yyy類型的xxx成員變量,當有幾個這樣的成員變量需要寫訪問函數時,好多的函數定義真是讓人煩透了,就算使用提供了方便模板的ide,也令人心煩,所以我有了以下想法,其實現實中的好多項目里早已運用了,這里只是提一下,如下代碼:
struct State {
? union {
??? int intV_;
??? bool boolV_;
??? char* rawStrV_;
??? // other members
? };
? State(const int v) : intV_(v) {}
? State(const bool v) : boolV_(v) {}
? State(const char* v) : rawStrV_() {}
? // other ctors
};
enum StateType{
? ST_WINDOWED,
? ST_ACTIVED,
? ST_WIDTH,
? ST_HEIGHT,
? ST_VERSION
};
class Renderer {
public:
? void setState(StateType st, State v) {
??? switch(st) {
????? case ST_WINDOWED:
????? { // ...
????? }break;
????? case ST_ACTIVED:
????? { // ...
????? }break;
????? // ...
????? default: assert(false);
??? }
? }
? State getState(StateType st) const {
??? switch(st) {
????? default:
????? case ST_WINDOWED: return windowed_;
????? case ST_ACTIVED: return actived_;
????? // ...
??? }
? }
private:
? int w;
? int h;
? char* versionDescription_;
? bool windowed_;
? bool actived_;
};
非常簡單明了!!!
優點:還是有些繁瑣,但不用寫一堆的函數定義體“{}”,這里只有兩對;容易產生高效的代碼
缺點:更改代碼時,代碼改動量較大
可以看出,這一管理策略正好與“狀態管理”的接口語義一致,使人感覺非常輕量。
這樣寫代碼效率及其低下(switch-case效率!!!),不能內聯不說,這種
switch-case語句也是C++里極力避免的。
一定要使用switch-case的話,考慮使用映射代替,效率很高。
你提到的“映射”是指std::map/std::multimap ?
“也容易在一個代碼段里理清狀態與狀態間的邏輯關系阿! ”,這個也許是個原因,但似乎沒什么有用的效果,個人見解。
"你提到的“映射”是指std::map/std::multimap ?",對這種應用來說,使用他們的開銷可能比switch-case還大(如果狀態成員有成百上千個,那到可以顯著提高性能),開始我沒仔細考慮,這個問題用映射做似乎比較麻煩,因為參數的類型不一樣,但非要做也是可以的,可以使用boost::any的Any(大概是這個名字),但這樣還不如switch-case呢。抱歉。
如果管理的狀態量不算很多的話,使用本文的簡單技術或set***()/get***()足夠了。
如果真遇到了大量的狀態管理,就像下面這樣:
struct State {
// 原來的代碼 。。。
// 增加的code
operator int () const { return intV_; }
operator bool () const { return boolV_; }
operator char* () const { return rawStrV_; }
};
這種削弱類型的東西 :)
然后再類中聲明一個含有State類型的容器,如std::map<StateType,State> states_;
然后寫:
void T::setWindowed(bool v) { states_[ST_WINDOWED] = v; /*...*/ }
bool T::getWindowed() const { return states_[ST_WINDOWED]; }
這樣做,算是個折衷吧!
還是多寫幾個函數方便
就是,一個類的實現被一個以上的人參與的話,請用此方式時再三考慮,建議在一開始把這種狀態管理的代碼包在一個class中,以便以后遇到問題時好集中處理,也不會蔓延到其它模塊,可以試試Hurb Sutter的Pimpl手法.