顯示實例化 問題


#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED
#include <iostream>
using namespace std;
template<typename C>
class A
{
public:

    template <typename T2>
    A(T2 v1, T2 v2);

    template<typename T>
    void myft(T);    //成員函數模板


    void myfunc()  //普通成員函數
    {

    }

    C m_ic;
};



#endif

#include "test.h"

//"顯式實例化“手段中的”實例化定義“,這種實例化定義只需要再一個。cpp文件寫就可以‘
// template A<float>;//編譯器遇到這段代碼就直接 實例化一個A<float>

    template <typename C> //先跟類的模板參數列表
    template <typename T2>  //再跟構造函數自己的模板參數列表
    A<C>::A(T2 v1, T2 v2)
    {
        cout<< v1 << "和"<<v2<<endl;
    }


//這裏是不準確的,原因看下文
//    template <typename C>​
//    template <typename T>
//    void A<C>::myft(T temp)    //成員函數模板
//    {
//        cout << temp << endl;
//    }

#include "test.h"
using namespace std;

//顯示實例化 手段中的 ”實例化聲明“
//extern template A<float>;//其他.cpp文件都這樣寫


int main()
{
    //爲了防止在多個。cpp文件中error: stray '\213' in program
    //,都實例化相同的類模板
    //所以,c++11 提供了 “ 顯式實例化”
    //通過顯示實例化,來減少開銷
    A<int> tsddd(2,4);
    cout << "Hello world!" << endl;
    return 0;
}
//建議:vs2017 不太推薦這個顯示實例化
//我用的是codeblocks,在執行    A<int> tsddd(3,4);時不能正確調用,只能調用無參構造函數
//test.cpp中的成員模板函數,無法正常使用。
//等我下載vs再來試試,電腦內存不足ing...
//codeblocks 好像不支持顯示實例化?。。。。

 

 

問題:發現一篇博文

c++類的模板成員函數申明和實現必須放在一起

2017年12月12日 17:32:04 wayen820 閱讀數:2721

 版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/qq_29573053/article/details/78784134

 

解釋如下:

C++中每一個對象所佔用的空間大小,是在編譯的時候就確定的,在模板類沒有真正的被使用之前,編譯器是無法知道,模板類中使用模板類型的對象的所佔用的空間的大小的。只有模板被真正使用的時候,編譯器才知道,模板套用的是什麼類型,應該分配多少空間。這也就是模板類爲什麼只是稱之爲模板,而不是泛型的緣故。

既然是在編譯的時候,根據套用的不同類型進行編譯,那麼,套用不同類型的模板類實際上就是兩個不同的類型,也就是說,stack<int>和stack<char>是兩個不同的數據類型,他們共同的成員函數也不是同一個函數,只不過具有相似的功能罷了。

如上圖所示,很簡短的六行代碼,用的是STL裏面的stack,stack<int>和stack<char>的默認構造函數和push函數的入口地址是不一樣的,而不同的stack<int>對象相同的函數入口地址是一樣的,這個也反映了模板類在套用不同類型以後,會被編譯出不同代碼的現象。

所以模板類的實現,脫離具體的使用,是無法單獨的編譯的;把聲明和實現分開的做法也是不可取的,必須把實現全部寫在頭文件裏面。爲了清晰,實現可以不寫在class後面的花括號裏面,可以寫在class的外面今天犯了這個錯誤,導致鏈接錯誤。下次記住了。

模板類成員函數的定義和聲明爲什麼要放在一個文件中

2018年07月25日 14:53:52 心如止水_03 閱讀數:574

“通常情況下,你會在.h文件中聲明函數和類,而將它們的定義放置在一個單獨的.cpp文件中。但是在使用模板時,這種習慣性做法將變得不再有用,因爲當實例化一個模板時,編譯器必須看到模板確切的定義,而不僅僅是它的聲明。因此,最好的辦法就是將模板的聲明和定義都放置在同一個.h文件中。這就是爲什麼所有的STL頭文件都包含模板定義的原因。”[1]

"標準要求編譯器在實例化模板時必須在上下文中可以查看到其定義實體;而反過來,在看到實例化模板之前,編譯器對模板的定義體是不處理的——原因很簡單,編譯器怎麼會預先知道 typename 實參是什麼呢?因此模板的實例化與定義體必須放到同一翻譯單元中。"[1]

"

《C++編程思想》第15章(第300頁)說明了原因:

模板定義很特殊。由template<…> 處理的任何東西都意味着編譯器在當時不爲它分配存儲空間,它一直處於等待狀態直到被一個模板實例告知。在編譯器和連接器的某一處,有一機制能去掉指定模板的多重定義。所以爲了容易使用,幾乎總是在頭文件中放置全部的模板聲明和定義。

"[2]

 

"

對C++編譯器而言,當調用函數的時候,編譯器只需要看到函數的聲明。當定義類類型的對象時,編譯器只需要知道類的定義,而不需要知道類的實現代碼。因此,因該將類的定義和函數聲明放在頭文件中,而普通函數和類成員函數的定義放在源文件中。

       但在處理模板函數和類模板時,問題發生了變化。要進行實例化模板函數和類模板,要求

編譯器在實例化模板時必須在上下文中可以查看到其定義實體;而反過來,在看到實例化模板之前,編譯器對模板的定義體是不處理的——原因很簡單,編譯器怎麼會預先知道 typename 實參是什麼呢?因此模板的實例化與定義體必須放到同一翻譯單元中。

"[3]

 

[1] 任何時候都適用的20個C++技巧. http://www.uml.org.cn/c++/20112284.asp 

[2]  爲什麼不能將類模板的聲明與類模板函數實現分開寫. http://blog.sina.com.cn/s/blog_684355870100jmjr.html

[3] 類模板和模板函數連接出錯處理. http://www.cppblog.com/kenny/archive/2011/04/23/144841.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章