十一假期後就有點懶散,好長時間都沒想起來寫東西了。另外最近在打LOL的S賽。接觸LOL時間不長,雖然平時玩的比較少,水平也相當菜,但是像這種大型的賽事有時間還是不會錯過的。主要能夠感受到選手們對競技的激情,對瞬息萬變的戰局的應變,非常精彩。KeKe~~。 這一篇主要對UVW的源碼討論來收個尾,就介紹 ...
十一假期後就有點懶散,好長時間都沒想起來寫東西了。另外最近在打LOL的S賽。接觸LOL時間不長,雖然平時玩的比較少,水平也相當菜,但是像這種大型的賽事有時間還是不會錯過的。主要能夠感受到選手們對競技的激情,對瞬息萬變的戰局的應變,非常精彩。KeKe~~。
這一篇主要對UVW的源碼討論來收個尾,就介紹一下項目中其他的一些好玩的東西,稍微豐富一下知識。
1、模版
之前說了很多東西,但是都把它給忽略了,對於C++的模版,很多人對此有看法,說它難以理解,編寫困難等等。
我們都知道,模版也是C++多態的一種,屬於編譯期多態,也就是說C++把很多運行期的工作加到編譯期了,你的代碼保持了在語言層面的抽象層次。然而實際上編譯器在編譯時卻對同類型模版的使用進行了特化。所以相比較運行時的多態,模版的運行性能是更好的,但是編譯的時間可能就稍長了一些。
雖然那些對模版的看法都講的過去,但是模版在應用中所帶來的作用是相當大的。舉一個最簡單的例子:
std::shared_ptr<uvw::TcpHandle> tcp = loop.resource<uvw::TcpHandle>();
這是我們項目中一個創建TcpHandle的語句,如果我們按照一般C的思路,寫出來的代碼很可能是這樣的:
TcpHandle* tcp = loop.resource(type);
OK,看上去很正常,但是暴露了很多問題,這個resource函數的原型應該是:
void* loop::resource(int type); 或者 Handle* loop::resource(int type);
它肯定是返回void*或者Handle這個基類的指針,但是你只能通過你對代碼的理解和type的值來判定,它返回的是TcpHandle*類型。萬一我不小心把返回類型寫成了UdpHandle*,它同樣繼承自Handle類,C++是沒有對此的檢測的。那這時候模版的價值就顯示出來了,它可以直接根據模版的類型,對返回的類型起到限製作用。避免了上面情況的出現。
再比如我們在 第二篇 中講static的時候,沒有模版就不能實現那樣的功能。
有些朋友在編碼的時候很少或者根本就不用模版,頂多在用一些容器的時候。或許因為就算用模版,也會造成上面提到的一些負面影響。所以很多人知道模版,但是不常使用,不常使用的東西往往也會忘的非常快,造成這樣一個不好的迴圈。如果模版可以解決切實的編碼問題,大膽一點用就是了,不要怕用錯,錯了才能更好的用嘛!
2、enum
enum就是枚舉類型,但是C++11對enum有擴展。先看這段代碼:
fs.hpp 55 ~ 69
enum class UVDirentTypeT: std::underlying_type_t<uv_dirent_type_t> { UNKNOWN = UV_DIRENT_UNKNOWN, FILE = UV_DIRENT_FILE, 。。。。。。 }; enum class UVCopyFileFlags: int { EXCL = UV_FS_COPYFILE_EXCL };
enum和enum class的區別,有下麵幾點:
1、如果在同一個頭文件中,有下麵的代碼:
1 enum HandleType{TCP,UDP,POLL,FS}; 2 enum StreamType{TCP,UDP,POLL,FS};
這是編譯不通過的,因為本身enum就相當於 #define 的一個集合,名字是不能一樣的。但是用 enum class 來寫,則是OK的,比如:
1 enum class HandleType{TCP,UDP,POLL,FS}; 2 enum class StreamType{TCP,UDP,POLL,FS};
但是使用的時候是需要加上作用域的。
2、我們都知道enum中的每個元素都是可以直接轉為int型的(對於不同的編譯器,可能類型不一樣)。但是 enum class 是不可以的。比如:
1 enum HandleType{TCP,UDP,POLL,FS}; 2 enum class StreamType{TCP,UDP,POLL,FS}; 3 4 int handleType = TCP; 5 int streanType = StreamType::TCP; //錯誤
第5行就會產生編譯錯誤,enum很容易被隱式的轉為int,在某種意義上,是enum的一種缺陷,所以enum class解決了這個問題.
另外enum class的元素是可以指定類型的,比如:
1 enum smallenum: int16_t 2 { 3 a, 4 b, 5 c 6 }; 7 8 enum class altitude: char 9 { 10 high='h', 11 low='l', 12 };
可以看到,這個 enum class中的 “class” 是可以省略的。那如果我有需求,要將enum class轉為需要的類型怎麼辦?比如上面的兩個例子,可以這樣搞:
1 smallenum s = smallenum::a; 2 int16_t i = static_cast<int16_t>(s); 3 4 altitude e = altitude::high; 5 char c = static_cast<char>(e);
當然,在switch 。。。 case。。。語句中是可以直接用的。
最後
到這裡源碼中關於語法一類的、使用的一些技術和方法就介紹到這裡。這些東西其實也不難,也許大家都知道,不知道的通過介紹也有一些瞭解了,主要是讓大家在看源碼的時候可以舒服點,排除一些障礙。
有些看官可能對項目中的代碼的書寫形式,使用方式等很多東西不是很習慣,但是我想說這應該就是現代C++的一個編碼模式。你可能在一個項目中看不見一個指針,看不見一個強轉,使用大量的模版,使用很多限制關鍵字,類實現和定義放在同一個文件,如同java一般,還有其他很多看不習慣的地方。但是當你熟悉了,明白了,習慣了,說不定效率就上升了。其實這些說到底還是要提升對C++的認知。
之後我會再找一些在比較好的項目來和大家分享,比如架構,演算法等方面的。由於水平有限,博客中若有錯誤,煩請指正。