2017-06-19 24 views
0

我正在製作一個小型系統,我希望能夠在整個系統中切換「詳細」文本輸出。使控制檯輸出成爲「詳細」的最快方法

我做了一個名爲globals.h:

namespace REBr{ 
    extern bool console_verbose = false; 
} 

如果這是真的我希望我所有的類打印一條消息到控制檯時,他們正在建設,自毀,複製或做幾乎任何東西。

例如:

window(string title="",int width=1280,int height=720): 
Width(width),Height(height),title(title) 
{ 
    if(console_verbose){ 
     std::cout<<"Generating window #"<<this->instanceCounter; 
     std::cout<<"-"; 
    } 
    this->window=SDL_CreateWindow(title.c_str(),0,0,width,height,SDL_WINDOW_OPENGL); 
    if(console_verbose) 
     std::cout<<"-"; 
    if(this->window) 
    { 
     this->glcontext = SDL_GL_CreateContext(window); 
     if(console_verbose) 
      std::cout<<"."; 
     if(this->glcontext==NULL) 
     { 
      std::cout<<"FATAL ERROR IN REBr::WINDOW::CONSTR_OPENGLCONTEXT: "<<SDL_GetError()<<std::endl; 
     } 
    } 
    else std::cout<<"FATAL ERROR IN REBr::WINDOW::CONSTR_WINDOW: "<<SDL_GetError()<<std::endl; 
    if(console_verbose) 
     std::cout<<">done!"<<endl; 
} 

現在你可以看到我有很多在構造IFS的。我真的不想這樣做,因爲這會減慢我的申請。我需要這樣做,儘可能快地移除「加載欄」(這有助於我確定程序停止運行的功能)。

什麼是最好的/最快的方法來完成這個?


萬萬在我的系統是命名空間REBr

+1

將''console_verbose'標記爲'constexpr'。如果它們的表達式被評估爲「false」,那麼它顯然會導致編譯器優化所有的「if」。 – Alexey

+1

此外,如果你想避免輸入'if(...)''每一次,只需定義一個宏#define VERB_STREAM if(console_verbose)std :: cout'並使用它像'VERB_STREAM <<「生成窗口#」<< this-> instanceCounter <<' - ';' – chtz

+0

你應該也看到這個問題:https://stackoverflow.com/q/6692238/1632887 – seleciii44

回答

1

一些變體實現的是:

  1. 使用一些記錄庫。這是最好的選擇,因爲它給你最大的靈活性和一些有用的經驗;)你不必設計一些東西。例如,看看Google GLOG
  2. 定義一些宏,允許您通過僅更改宏來打開/關閉所有這些日誌。但要正確地寫出這樣的marco並不那麼容易。
  3. 將您的條件標記標記爲constexpr。這樣你可以切換標誌,並且根據其值,編譯器將在已編譯的程序中優化if。但if仍然在代碼中,所以它看起來有點笨重。

無論如何,所有這些選項都需要程序重新編譯。不用重新編譯就不可能達到最大速度。

+0

非常豐富,非常詳細,包括多個答案。謝謝! – MoustacheSpy

0

我經常使用支持調試水平的Logger類下。一個調用可能如下所示:

logger->Log(debugLevel, "%s %s %d %d", timestamp, msg, value1, value2); 

Logger類支持多個調試級別,因此我可以微調調試輸出。這可以在任何時候通過命令行或調試器進行設置。 Log語句使用非常像printf的可變長度參數列表。

+0

您究竟如何實現這個課程?你是否爲你想要使用它的每個函數創建一個實例,或者你在創建一個全局實例。如果是的話,爲什麼不在一個名稱空間內創建一些函數和變量? – MoustacheSpy

+0

@MoustacheSpy:我在我的主例程中實例化一個全局實例,以便啓動是可預測的。由於我的應用程序幾乎完全是面向對象的,所以我使用類/方法來覆蓋函數,但這有點武斷,超出了封裝的明顯優勢。另外,如果多個線程正在訪問日誌,則需要線程安全保護。該類可以使用多態性使用線程安全和非線程安全的調用。 – Bruce

0

Google's logging module在業界廣泛使用,並支持您可以從命令行設置的日誌記錄級別。例如(從他們的資料爲準)

VLOG(1) << "I'm printed when you run the program with --v=1 or higher"; 
VLOG(2) << "I'm printed when you run the program with --v=2 or higher"; 

您可以在這裏找到的代碼https://github.com/google/glog並在doc/文件夾中的文檔。