2017-02-21 59 views
-1

我想實現一個通用設置結構來訪問我的應用程序的所有設置在一個地方。應用程序的每個模塊都有自己的設置類/結構。我想在常規設置結構中定義一個具有每個模塊設置類型的成員。爲了使事情更容易,我想定義一個REGISTER宏,爲每個模塊設置創建一個新的成員。C++使用宏來定義一個類的類成員

事情是這樣的:

struct Settings 
{  
    // I know this is not working 
    #define REGISTER_SETTINGS(settings) \ 
      settings _##settings = ##settings(); 
}; 

struct ServerSettings 
{ 
    int port = 8080; 
    string ip = "0.0.0.0"; 
}; 

REGISTER_SETTINGS(ServerSettings); 

struct WindowSettings 
{ 
    int width = 640; 
    int height = 480; 
    string title = "window"; 
}; 

REGISTER_SETTINGS(WindowSettings); 

在結束我的設置結構應該是這樣的:

struct Settings 
{ 
    ServerSettings _ServerSettings = ServerSettings(); 
    WindowSettings _WindowSettings = WindowSettings(); 
}; 

我不知道我應該怎麼弄宏擴展在那裏。

+7

在C++中使用宏的單詞指南:**不要**。 –

+0

您需要從宏中刪除分號,對於一個 – StoryTeller

+0

爲什麼要在結構中定義宏? – user463035818

回答

2

您應該避免使用宏。它在我眼中甚至沒有意義,因爲你是程序員,只需將這兩行寫入設置結構中,並且你很好...... 但是如果你仍然想要這樣的函數,可以使用內聯功能。

0

你可以這樣做:

#define REGISTER_SETTINGS(settings) \ 
     settings _##settings = settings(); 

注意到沒有 '##' settings()之前。

但是:

  1. 正如已經在評論中指出:做的更好使用宏。
  2. 這會不會導致你所期望的,例如:

    struct Settings 
    { 
        ServerSettings _ServerSettings = ServerSettings(); 
        WindowSettings _WindowSettings = WindowSettings(); 
    }; 
    

    ,但它會造成在放置物品,其中宏被稱爲:

    struct Settings 
    ... 
    struct ServerSettings 
    ... 
    ServerSettings _ServerSettings = ServerSettings(); 
    
    struct WindowSettings 
    ... 
    WindowSettings _WindowSettings = WindowSettings(); 
    
  3. 我會建議使用一些creational pattern像(摘要)工廠或工廠方法。

1

正如其他人所說,最好避免宏完全。

但是,要回答這個問題的提出....

聲明具有成員是其他struct類型的實例的struct類型,編譯器必須已經看到那些載類型的聲明。所以簡單地改變定義的順序。

struct ServerSettings 
{ 
    int port = 8080; 
    string ip = "0.0.0.0"; 
}; 

struct WindowSettings 
{ 
    int width = 640; 
    int height = 480; 
    string title = "window"; 
}; 

struct Settings 
{  
#define REGISTER_SETTINGS(settings) \ 
     settings _##settings = ##settings() 

    REGISTER_SETTINGS(ServerSettings); 
    REGISTER_SETTINGS(WindowSettings); 

     // etc 

#undef REGISTER_SETTINGS 
}; 

#undef防止struct Settings定義之外所使用的宏存在。

雖然有一個關鍵問題。這將創建以下劃線和大寫字母開頭的標識符。這些標識符由C++標準保留,並且使用它們會導致您的代碼具有未定義的行爲。避免這種情況的一種方法是將宏更改爲

#define REGISTER_SETTINGS(settings) \ 
    settings a_##settings = ##settings() 

它可以防止創建保留標識符。

二,申報

Type name = Type(); 

基本默認,初始化name,所以在功能上等同於

Type name; 

所以,你可以進一步簡化宏

#define REGISTER_SETTINGS(settings) \ 
    settings a_##settings 

正如我儘管如此,在最開始時說,最好避免使用宏年。宏只是掩蓋了這樣做的事實;

// definitions of ServerSettings and WindowSettings here 

struct Settings 
{  
    ServerSettings a_ServerSettings;  
    WindowSettings a_WindowSettings; 
}; 

這是很容易讀取宏的混淆,你要使用。顯然,你可以使用你喜歡的Settings成員的任何命名約定。