2012-12-15 41 views
1

我需要爲我的大學作業做一個基於函數(或命令)的語言的C++解釋器。解釋器必須讀取輸入文件,提取單詞(字符串),生成命令並執行它們。所有的命令都是從一個普通的超類繼承而來的類(例如,Command),它有一個名爲execute的虛擬方法。對於從輸入文件讀取的每個單詞,創建一個命令並存儲在vector<Command>中。我想使用一個哈希表,其鍵是命令(字符串)的名稱,其值是某種對象,它允許我創建一個特定的類(或讓我訪問構造函數的特定類),可以輕鬆地爲每個單詞創建類,而不是使用if-else-if鏈。C++中的「類」(不是對象)的哈希表

現在,我打算用一個名爲generate的虛擬方法創建一個CommandGenerator類,它將返回一個新的Command對象。我的命令散列表的值將是CommandGenerator類的對象。所以我從其中衍生出許多其他所有命令的子類,它們返回從Command派生的特定新對象。

但是,這樣的事情是否已經存在?還是有更好的方法來做到這一點?是否有任何類型的對象可以從類中提取來表示它?

回答

1

如果每個命令都是Command的子類,那麼爲什麼不使用std::vector<Command*>並將指針指向每個子類的實例?然後,您可以遍歷該向量並調用您的虛擬execute函數。

你可以得到關於放置類矢量最接近的是boost::fusion::vector。但不能在運行時填充,不能在你的具體情況下使用。


假設您可以使用C++ 11。如果你可以定義命令只是一個execute功能,你可以這樣做:

map<string, function<void()>> cmds = { 
    make_pair("print1", [](){ 
     cout << "1" << end; 
    }), 
    make_pair("print2", [](){ 
     cout << "2" << end; 
    }), 
    make_pair("print3", [](){ 
     cout << "3" << end; 
    }) 
}; 

,然後把命令上的向量與:

vector<function<void()>> list; 
list.push_back(cmds["print1"]); 
list.push_back(cmds["print1"]); 
list.push_back(cmds["print2"]); 

然後,只需用一個循環中執行:

for (function<void()>& cmd : list) 
    cmd(); 

這應該打印112到屏幕上。但是,如果你在速度上關心很多,那麼請做很多ifs。

+0

「如果每個命令都是Command的子類,爲什麼不使用std :: vector 並將指針指向每個子類的實例?然後你可以遍歷vector並調用你的虛擬執行函數,「好吧,這就是我要用剛剛創建的對象做的事情:把它們推到一個vector上並遍歷vector,調用'execute',但是我的問題必須根據從文件中讀取的名稱生成這些對象,而不使用if-else-if如果對於每個名稱。 – LuisABOL

+0

@Luis查看編輯答案 –

+0

好多了,man!你有鏈接到任何'函數<>'引用,因爲通過在谷歌上鍵入「C++函數<>」,我只能找到在C++中的函數或函數聲明的概念... ... – LuisABOL

1

您遇到的基本問題是:您將該類的名稱視爲字符串,並且希望使用該名稱創建一個類。您必須以某種方式手動執行此翻譯,就像您提到的那樣。這已經在這裏討論過幾次了,如Instantiating classes by name with factory patternLooking for a better C++ class factory。唯一的補充,我會在這裏:使用優秀的舊宏,因爲他們有一個字符串操作符。例如:

#include <stdio.h> 
#define CREATEOBJ(clss,command) if (strcmp (#clss, command)==0) return new clss; 
class Base { 
public: 
    virtual const char *name()=0; 
}; 
class A : public Base { 
public: 
    const char *name() {return "I am an A";} 
}; 
class B : public Base { 
public: 
    const char *name() {return "I am an B";} 
}; 
Base *makeInstance (const char *nm) { 
    CREATEOBJ(A,nm); 
    CREATEOBJ(B,nm); 
} 
int main() { 
    printf ("%s\n", makeInstance ("A")->name()); 
    printf ("%s\n", makeInstance ("B")->name()); 
} 
當然

可以讓它更好用含有字符串和一些函數指針或發電機級指針的哈希表,但這個想法是一樣的:添加一個新的類,只是再加一個CREATEOBJ-thingy。