2012-12-14 102 views
2

我有用作運算符5類:太多類具有相同的概念

TurnOn , TurnOff , PushBox , Exit , Enter 

我有對於每種類型中,保持該類型的描述的字符串。

例如:

class Places { 

enum Type { Room1 ,Room2 ,Room3 ,Room4 }; 


// more stuff 

}; 
TurnOn turnOn(Places::Room1); 
string turnOnString = "TurnOn(Room1)" ; 

我想存儲在地圖中的信息,所以我必須爲每個操作員5個地圖:

map <string , TurnOn > opeatorTurnOn; 
map <string , TurnOff > opeatorTurnOff ; 
map <string , PushBox > opeatorTPushBox ; 
map <string , Exit > opeatorExit ; 
map <string , Enter > opeatorEnter ; 

但現在我有5點的地圖,同一個概念:帶有其運算符的字符串。

如何將運營商存儲在同一個地圖中,這樣我就不必擁有同一個概念的5個地圖?

+4

這似乎是一個有缺陷的設計,5個運算符類不是從基類'運算符'派生的嗎?從基類中派生所有按鈕並在預定義數字時在整個程序中動態創建新操作符會更有意義。例如'operator * turnOn = new TurnOn;' –

+0

@ Need4Sleep:(1)這應該是一個答案。 (2)我會嘗試修復我的設計。謝謝 ! – ron

回答

3

這取決於你的操作符是如何實現的(我們有很少的信息),但我會做地圖可調用的,類似這樣的東西:

#include <iostream> 
#include <functional> 
#include <map> 

struct op1 
{ 
    void operator()(int i) { std::cout << "op1::operator() " << i << "\n"; } 
}; 

struct op2 
{ 
    void operator()(int i) { std::cout << "op2::operator() " << i << "\n"; } 
}; 

int main() 
{ 
    std::map<std::string, std::function<void(int)>> ops; 
    ops["1"] = op1{}; 
    ops["2"] = op2{}; 
    ops["1"](42); 
    ops["2"](42); 
} 

你也可以隨時換的OPS在lambdas中如果你不使用operator()重載。

2

使它們都從一個基類繼承,存儲指向基的指針並使用多態性。

+0

我想避免多態,因爲每個類都有不同的方法。 – ron

+0

您可以擁有一個polymorhpic入口點(比如'func()'),並且一次在該上下文中您將確切知道該類是什麼類型,並且存在可用的操作。 – Chad

+1

-1沒有足夠的提升。 – Puppy

1

您不能在映射(或任何其他STL容器)中存儲異構數據類型。

最簡單的解決方法是將它們全部從一個基類繼承下來,並將基類存儲在您的映射中。編輯:我沒有注意到避免多態的願望(雖然,我真的不明白爲什麼)。無論如何,我認爲boost :: any或boost :: variant可能對你有幫助。您可以將它們全部存儲爲boost :: any。 http://www.boost.org/doc/libs/1_52_0/doc/html/any.html

+0

看到其他答案,他指出他不想要一個基類。 –

0

boost::variant通常用於這樣的事情。

+0

爲什麼downvote?考慮到當前已知的設計信息,這似乎是非常有效的答案。 – KillianDS

+1

和我-1也 - 因爲太多的提升(偉大的理由倒下DeadMG不是嗎?)。 – doc

+1

我知道,其實我並沒有低估那個人。這是一個模因。 – Puppy