2017-02-02 26 views
0

我有一個C++應用程序,其中main()實例化對象MyApp,然後將該對象傳遞給ReadConfig函數。如何通過函數指針調用具有不同簽名的C++函數

ReadConfig打開一個基於文本的文件,解析它並調用相應的MyApp方法來配置它。

class MyApp 
{ 
private: 

public: 
    void SetRate(uint16_t); 
    void EnableLogging(bool); 
    void SetAddress(uint32_t); 
}; 

我想讓維護ReadConfig變得很容易,因爲隨着新的公共方法被添加到MyApp,它可以像更新表一樣簡單。我提出了以下解決方案,但我不喜歡它。由於必須確保我將0放在正確的位置,因此很難維護。

下面是我已經能夠解決的一個例子。任何建議,使這個更好,將不勝感激。注意我在嵌入式工作,所以我們使用的C++編譯器不支持C++ 14 &,這沒有任何提升。我想避免使用任何STL庫來理解自己做這件事的機制。

以下是我有:

enum ARGTYPE {TBOOL, TUINT16, TUINT32}; 

template<typename TOBJ, typename TARG> 
struct TSetting 
{ 
    void (TOBJ::*FSet)(TARG); 
}; 

template<typename obj> 
struct SETTINGFN 
{ 
    const char      *setting_name; 
    ARGTYPE       Targ; 
    TSetting<obj,bool>    HBool; 
    TSetting<obj,uint16_t>   HUint16; 
    TSetting<obj,uint32_t>   HUint32; 
}; 

SETTINGFN<MyApp> MyAppSettings[] = 
{ 
    "logging" ,TBOOL,  &MyApp::EnableLogging, 0,0,0 
    ,"maxrate" ,TUINT16,  0,0,0,&MyApp::SetRate 
    ,"address" ,TUINT32,  0, &MyApp::SetAddress, 0,0 

}; 
unsigned int MyAppSettings_Count = sizeof(MyAppSettings)/sizeof(SETTINGFN<MyApp>); 

然後,因爲我讀的配置文件,並解析它,我調用一個函數來處理通過函數指針調用實際MyApp的功能。該功能如下:

bool AppSetting(MyApp &E, TObjnode &node) 
{ 
    bool rval = false; 

    for(unsigned int i=0; i<MyAppSettings_Count && !rval; i++) 
    { 
    if(node.GetName() == MyAppSettings[i].setting_name) 
    { 
     rval = true; 

     switch(MyAppSettings[i].Targ) 
     { 
     case TBOOL: 
      (E.*MyAppSettings[i].HBool.FSet)(node.GetValue().AsBool()); 
     break; 

     case TUINT16: 
      (E.*MyAppSettings[i].HUint16.FSet)(node.GetValue().Value()); 
     break; 

     case TUINT32: 
      (E.*MyAppSettings[i].HUint32.FSet)(node.GetValue().Value()); 
     break; 
     } 
    } 
    } 

    return(rval); 
} 
+0

纔算及格的字符串到每個二傳手,並讓他們撥打特定類型的可重複使用的解析代碼?然後所有的制定者可以是相同的類型。接受字符串並調用解析函數和類型安全的setter的蹦牀可能會更好。 –

+1

因此......爲了避免每次添加新屬性/設置器時必須向配置調度例程添加函數調用,每次添加新屬性/設置器時都希望更新專有數據結構?對於他自己的,我想... –

+0

我想到了這些,但我希望避免改變當前的功能簽名或添加新的 – Eric

回答

2

您設計中的刺是不同的參數類型。

如果參數被抽象爲一個結構,那麼函數可以簡化爲一個固定的簽名。

通過使用鹼的結構,簽名和更通用的:

struct Arguments_Base 
{ 
}; 

void SetRate(Arguments_Base& ab); 
void EnableLogging(Arguments_Base& ab); 
void SetAddress(Arguments_Base& ab); 

通過具有均勻的簽名,函數指針功能對象可以在表或圖中使用,使搜索更容易。搜索引擎應該是通用的,並且取決於數據的大小,以便只需要更改數據(例如表格),而不是搜索引擎。

每組參數都應該從Arguments_Base類派生。該函數然後可以使用基類引用dynamic_cast

參見:工廠設計模式,Visitor設計模式,雙重分派

+0

信不信由你,我想到了這一點,但我希望避免改變當前的功能簽名或添加新的 - 但這是優雅的。 – Eric

+0

Yuck。 dynamic_cast的。甚至配置文件讀取。 – rubenvb

+0

@rubenvb如果基類提供了派生類可以超載的方法,則不需要動態轉換。認爲NVI設計模式。或者,如果像Ben Voigt所建議的那樣,基類可以簡單地進行轉換,而Arguments_Base則是可以返回值(int,bools等)的String類。 – Eric