為什麼 c++中函數模板和類模板的 聲明與定義需要放到一起?

來源:互聯網
上載者:User

標籤:span   text   聲明   code   出錯   檔案中   兩種方法   why   問題   

將模板的聲明與定義寫在一起實在很不優雅。嘗試用“傳統”方法,及在.h檔案裡聲明,在.cpp檔案裡定義,

然後在main函數裡包含.h標頭檔,這樣會報連結錯誤。why!!!!!!!!!!!!!

這是因為函數模板要被執行個體化後才能成為真正的函數,在使用函數模板的源檔案中包含函數模板的標頭檔,

如果該標頭檔中只有聲明,沒有定義,那編譯器無法執行個體化該模板,最終導致連結錯誤。(類模板同樣!!)

 

 1 //---------------test.h-------------------//  2  void f();//這裡聲明一個函數f  3 //---------------test.cpp--------------//  4  #include”test.h”  5  void f()  6  {  7  …//do something  8  } //這裡實現出test.h中聲明的f函數  9 //---------------main.cpp--------------// 10  #include”test.h” 11  int main() 12  { 13      f(); //調用f14  }

編譯時間會產生兩個obj檔案,main.obj和test.obj,而在main.obj裡並沒有f函數的二進位代碼,這些代碼實際存在於test.obj中。在main.obj中對f的調用只會產生一行call指令,call指令的地址由連結器產生。

 

 1 //-------------test.h----------------//  2  template<class T>  3  class A  4  {  5     public:  6      void f(); //這裡只是個聲明  7  };  8 //---------------test.cpp-------------//  9  #include”test.h” 10  template<class T> 11  void A<T>::f() 12  { 13  …//do something 14  } 15 //---------------main.cpp---------------// 16  #include”test.h” 17  int main() 18  { 19      A<int> a; 20     a. f(); 21  }

我們知道模板有個具現化的過程,在未被使用的時候是不會產生二進位檔案的。所以當連結器去找f函數的地址時,因為在這之前沒有調用過f(),test.obj裡自然就沒有f函數的二進位代碼,於是就會報錯。

 

要使模板聲明與定義分開也不是沒有辦法。

第一種辦法是在main函數裡包含cpp檔案

 1 //-------------test.h----------------//  2  template<class T>  3  class A  4  {  5     public:  6      void f(); //這裡只是個聲明  7  };  8 //---------------test.cpp-------------//  9  #include”test.h” 10  template<class T> 11  void A<T>::f() 12  { 13  …//do something 14  } 15 //---------------main.cpp---------------// 16  #include”test.cpp” //careful!!!!!!!!!17  int main() 18  { 19      A<int> a; 20     a. f(); 21  }

這樣三個檔案的內容通過include實際上包含在同一個檔案裡,自然就不會出錯了

 

 1 //-------------test.h----------------//  2  template<class T>  3  class A  4  {  5     public:  6      void f(); //這裡只是個聲明  7  };  8 #include<test_impl.h>
9 //---------------test_impl.h-------------// 10 template<class T> 11 void A<T>::f() 12 { 13 …//do something 14 }
15 //---------------main.cpp---------------// 16 #include”test.h” 17 int main() 18 { 19 A<int> a; 20 a. f(); 21 }

這兩種方法實際上都是包含編譯,沒有本質的區別,不過感覺第二種方法看起來比較舒服

 

 1 //-------------test.h----------------//  2  template<class T>  3  class A  4  {  5     public:  6      void f(); //這裡只是個聲明  7  };  8 //---------------test.cpp-------------//  9  #include”test.h” 10  template<class T> 11  void A<T>::f() 12  { 13  …//do something 14  } 15 template class A<int>;//!!!!!!!!!!在這裡實現了具現了類型  這樣編譯就不會有問題了  但是這樣不太好  自己想為什麼 !!!16 //---------------main.cpp---------------// 17  #include”test.h” 18  int main() 19  { 20      A<int> a; 21     a. f(); 22  }

 

差不多了吧 就這樣OK了  其實是看的別人的部落格!

 

為什麼 c++中函數模板和類模板的 聲明與定義需要放到一起?

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.