看了會glog使用文檔,很快就被下面的語法形式吸引了,這顆語法糖,真是太完美了。
1
LOG(INFO) << "Found " << num_cookies << " cookies";
2
CHECK(fp->Write(x) == 4) << "Write failed!";
3
符號“<<”,第一眼就能理解,使用了流對象重載操作符“<<”的方法。
問題是,如果LOG(INFO)實際上是一個流對象的話,那它怎么做到“在禁止輸出日志時不編譯“<<”右邊的代碼”呢?
要知道LOG4cpplus,可以是用了下面的語法結構才實現的,依靠最后那個括號。glog的語法顯然更勝一籌了。
1
LOG(INFO,"Found" << num_cookies << " cookies");
于是,跟蹤代碼,總于一窺真面目,大為感嘆。翻譯成原始代碼,應該這樣的,
1
LogMessage().stream() << "Found " << num_cookies << " cookies";
巧妙之處,就在于LogMessage是一個類,LogMessage()生成了一個臨時局部對象,它的生命期僅在這一行代碼范圍內。
就是說,這行結束的時候,LogMessage就被析構,在析構函數中,去執行真正的日志輸出。
寫上面例子,是為了引出本文真正的主題,利用C++對象的生命期來實現特殊代碼控制流程。
早年,學習Basic語言的時候,聽老師說了結構化編程中流程控制的三大元素“順序、選擇、循環”,真以為有了三大元素,便無所不能了,其他的都是多余的。
但實際上,一個例外便是:在一個作用域開始時,執行一些代碼;在作用域退出時,執行另一些代碼。比如,Win32上的句柄管理,獲取了句柄,最后一定要釋放。
我個人認為,這種流程控制,在現代C++編程中是如此重要,為其提供專門語法機制毫不為過。
然而,C++前輩們用一種可說巧妙,也可卑劣的方式,來處理這個問題,即利用對象在作用域中的構造與析構。
說它卑劣,是因為如此重要的特性,在C++教材里是找不到,使它得不到應有的重視。
當然不管怎么說,這個特性是C++優于C的極少特例之一。
總結一下,我們可以在四種對象作用范圍內,實現上述的特殊流程控制:
1. 全局對象生命期。一般不推薦使用全局變量,沒有多少實際意義;
2. 類成員變量,即類生命期。最典型的就是智能指針了。
3.局部變量,即函數中的塊作用域。這是最普遍的,比如什么互斥量守護,資源句柄守護等等。
4.局部匿名變量(不知道是否該這樣命名),在代碼行的作用域。這很少見,glog算是見到的第一個了。