2010-03-06 43 views
5

我正在研究音譯工具。我有兩個模塊詞法和翻譯器。 Lexer從輸入文本中生成令牌。根據當前選擇的語言,我必須調用適當的翻譯程序。根據變量的值執行功能 - C++

我想出了幾個想法來做到這一點。首先是創建一個名爲base_translator的基類,並提供每個譯者必須覆蓋的虛擬方法(translate())。現在創建一個工廠translator_factory並用語言名稱調用create()。這個工廠將返回適當的實例。

但是,這似乎是工程。所以我想出了另一種方法,我有一個像下面這樣的結構。

struct translator 
{ 
    const char* name; 
    void (*fp)(); 
}; 

它只是保留一個語言名稱和一個可以處理它的函數指針。用法如下:

static translator translators[] = { 
    {"first", first}, 
    {"second", second} 
}; 
const char* language = /* */; 
for(int i = 0; i < 2; i++) { 
    translator *t = translators + i; 
    if(strcmp(t->name, language) == 0) { 
     t->fp(); 
     break; 
    } 
} 

這種方法非常簡單,易於維護。但我想知道,這是解決問題的最佳方法嗎?你有什麼建議可以讓這個更好嗎?

任何幫助將是偉大的。

+0

你的第二種方法僅僅用C風格模擬C++的運行時多態(虛函數)。與C++中內置的對OOP的支持相比,它沒有任何優勢。 – 2010-03-06 16:44:59

回答

3

你的第二種方法對你來說可能看起來比較簡單,只有兩個項目(對我來說它不......),但是從長遠來看,它更容易出錯並且難以維護。無論何時添加新的語言,都需要至少在兩處觸摸代碼。 (並且相信我:即使這看起來似乎不太可能,但幾乎不可避免地會發生......)如果您忘記更新循環邊界,您的代碼中會有一個無聲的錯誤。而且,這個實現比多態的要慢得多:你需要遍歷數組並在每次調用之前比較字符串(而不是在vtable中查找指針)。

我肯定會使用一個工廠。除了上述的好處,它是一個衆所周知的設計模式,使其更容易理解。因此,維護你的代碼後的人不會詛咒你那麼多;-)

更新:工廠也可以返回一個函數指針。在這種情況下,我仍然會在內部使用functors,因爲這些是具有上述所有好處的完整課程。還有一點,沒有明確提到:他們(作爲真實的對象)可以存儲狀態,而普通函數不能。這可能會在以後發生很大的變化,並簡化您的設計。當然,一旦你擁有了工廠界面,你可以輕鬆地將你的產品的內部表示從普通函數改變爲函子(和後面)。

+0

謝謝。工廠更有意義。工廠如何返回函數指針而不是多態實例? – 2010-03-06 15:50:06

+0

@Appu看到我的更新。 – 2010-03-06 16:22:20

+0

感謝他們所有人的幫助。對此,我真的非常感激。 – 2010-03-07 02:43:25

5

這對於抽象類和虛擬函數來說通常是一個幸運的用例。我不明白你爲什麼認爲它是「過度工程」...... o_O

問題是要定義一個合約,以便你的代碼很容易擴展,而「主代碼」沒有擔心實際的實施細節。

2

兩種解決方案都適用於您所述的問題。如果問題空間增大,工廠可能會更好。例如,如果將來還需要另一種語言相關類或函數,則可以擴展工廠以返回它。函數指針表需要更多的更改來處理類似的事情。我會去工廠。問題領域一直在增長。