學藝不精而慚愧--論C++模板類的使用
自己斷斷續續地使用C++也有一段時間了。有些時候產生了自滿的情緒。覺得自己對C++的語言特性已經知道的幾乎相同了,在語法方面沒有什麽難倒我的地方了,如今所要做的是依據實際問題編敲代碼,問題的難點在於算法的設計和分析。在於解決這個問題的策略了。
然而今天下午的一次經歷給自己當頭一棒:永遠不要自滿,要保持一顆謙虛的學習的心。
1 問題的產生
我在實現[書][1]中219頁的list的contiguous結構時。依照我的慣性,寫了兩個文件:rblist.h和rblist.cpp,分別為類定義和方法的詳細實現。rblist.h中包括了模板類的定義。我又寫了測試程序testList.cpp來測試這個連續存儲的表結構時遇到了麻煩。
我使用的編譯命令為:
g++ Utility.cpp rblist.cpp testList.cpp -o testList
而在testList.cpp中我使用的是#include "rblist.h"
這條預處理指令。編譯出錯例如以下:
我前後幾次確認代碼沒錯,檢查幾遍還是編譯不通過。我又將rblist中的代碼刪減到只剩一個方法仍然編譯只是。沒辦法唯獨通過網上搜索解決的方法了。果真找到了解決的方法。代碼和編譯命令保持不變。而只將testList.cpp中的包括指令改為#include "rblist.cpp"
就順利通過編譯了。
我對預包括指令包括cpp文件的做法感到非常奇怪。
我從沒見過常常包括頭文件的命令可以用於包括cpp文件,並且可以保證編譯成功。並且網上的那位朋友指出,這是使用模板類easy犯的錯誤。我對此產生疑問。在我所讀過的不論什麽教科書中,從沒見過#include "rblist.cpp"
這樣的用法,我也對這樣的用法感覺非常的不舒服。
我決定對該問題一探到底。
2 對模板類用法的在認識
我曾經讀過[Bruce Eckel的書][2],對當中關於template class的介紹已經模糊了。但憑我的直覺。一定不會使用#include "rblist.cpp"
這樣的方法來使用模板類,其實也正驗證了我的直覺。該書給出了4中方法使用模板類:
- Inline function definition: 將方法的定義寫在類的聲明中,同一時候將main()函數與該模板類寫在同一個文件裏。這樣的方法簡單易用,通常出如今教科書中,實際的project項目中根本不會用這樣的方式使用模板類。初學C++的時候我按此方法練習了模板類的使用。也正是由於此方法讓我誤覺得我已經掌握了模板類的用法。
- Non-inline function definitnion: 該方法將類函數定義在類聲明的外部,函數定義和類聲明仍然在同一個文件裏。同一時候用於測試的main()函數也在同一文件裏。最後整個文件為cpp文件。這樣的方法給出了模板類的定義的新視角。將函數從類聲明分離出去。但由於它們仍然在同一文件裏,在源文件頭部仍然不須要出現
#include 模板類
的命令。這樣的方法以及前一種方法不會產生本文遇到的問題。
- Header files: 這樣的方法將整個模板類聲明和定義統一寫於一個頭文件.h中。原文這樣說: “Don’t put in anything that allocates storage,”, but template definitions are special. Anything preceded by template<..> means the compiler won’t allocate storage for it at that point, but will instead wait until it’s told to. So you’ll almost always put the entire template declaration and definition in the header file, for ease of use. 我採用此方法又一次寫了一個文件rbList2.h文件,將模板裏List的聲明和定義統統寫在裏面。然後使用
#include "rblist2.h"
將其包括在testList.cpp中。使用g++ Utility.cpp testList.cpp -o testList
編譯,順利通過編譯。我是比較認可這樣的方式使用模板類的。我看到曾經閱讀[書][2]時對應的句子上面做的標記,但是一到實際的問題中,還是把它忘記的一幹二凈。看來。要想學好語言,光看不練是不行的,要在看基本知識的前提下多多編程,通過實際編程經驗來提高編程能力。比方,我編程中遇到本文的問題,回頭來在去看曾經看過的書,經過這樣一個循環重復的過程後,對對應的問題理解的就深刻了。
曾經初學時候覺得非常難、非常高大上的概念和知識點就變得非常easy了。
知道了該概念出現的背景,它給編程人員帶來的優點等等,比只知道怎樣詳細的用要理解的深刻的多,並且也不會遺忘。
- [Bruce Eckel][2]也提到了模板類的聲明和定義分別寫在.h文件和.cpp文件裏的做法,但這只為了產生dll而不得不做的妥協的做法,指出該方法須要參考詳細的編譯器規定。這樣的方法非常少見。我想這可能就是
#include "rblist.cpp"
這樣的用法吧。
3 感悟
通過今天這個經歷,使我認識到:
- 永遠保持一顆謙虛的心非常重要。
不要自滿。在該學習的地方停止學習了。
- 學習編程的最好的做法就是多多編程。編的越多,當中感覺神奇的地方就會變得越來越少了,自己也就會越來越充實。
[1]: Robert L. Kruse and Alexander J. Ryba. Data Structures and Program design in C++. Upper Saddle River, 2000.
[2]: Bruce Eckel. Thinking in C++ Volume 1. 2nd. 2000.
學藝不精而慚愧--論C++模板類的使用