中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

類模板的分離編譯

發布時間:2020-06-24 08:46:18 來源:網絡 閱讀:696 作者:稻草陽光L 欄目:開發技術

  一直覺得模板類是特別神奇的東西,它可以構造出不同類型的對象,使代碼更加的靈活。這個過程就是類模板的實例化。

  我們使用類的模板寫一個stack類:

#include<assert.h>
#include"Seqlist1.h"
using namespace std;
template<class T,template<class> class Container  = Seqlist>
class Stack
{
public:
	void Push(const T& x)
	{
		_con.Pushback(x);
	}
	void Pop()
	{
		_con.Popback();
	}
	bool Empty()
	{
		return Size() == 0;
	}
	size_t Size()
	{
		return _con.Size();
	}
	T& Top()
	{
		size_t size = Size();
		assert(size > 0);
		return _con[size - 1];
	}
	void print()
	{
		_con.Print();
	}
	T& operator[](size_t index)
	{
		return _con[index];
	}
protected:
	Container _con;
};

  其中我們可以傳入不同類型的T,class Continer是類型T的一個容器,這里默認是用自定義的一個順序表來當容器。編譯器就會構造出不同的代碼出來。

  這樣的實現方式是在類內定義成員函數,并把整個類放在.h中,這種方式叫做類模板的包含模式。這樣的定義方式是有好處的,要使用Stack這個類,只要在頭文件內包含類體就可以了,編譯器很容易就可以找到類的定義。當然這種方式是有弊端的,如果一個類的成員函數個數很多并且很復雜,無疑在你去閱讀或者修改定義的時候會讓人很頭疼,不能快速找到成員函數的定義。

  還好C++提供了另外一種方式——將成員函數的聲明放在類體內.h中將函數的定義放在.cpp中,就相當與類外定義,我們把這種方式叫做類模板的分離模式。這樣寫出來的代碼是很美觀的,并且易于修改。

//.h文件
#include<assert.h>
#include"Seqlist1.h"
using namespace std;
template<class T,template<class> class Container  = Seqlist>
class Stack
{
public:
	void Push(const T& x);
	void Pop();
	bool Empty();
	size_t Size();
	T& Top();
	void print();
	T& operator[](size_t index);
protected:
	Container _con;
};

//.cpp文件
//類外定義

template<class T,template<class> class Container  = Seqlist>
void Push(const T& x)
{
_con.Pushback(x);
}


template<class T,template<class> class Container  = Seqlist>
void Pop()
{
_con.Popback();
}

template<class T,template<class> class Container  = Seqlist>
bool Empty()
{
return Size() == 0;
}

template<class T,template<class> class Container  = Seqlist>
size_t Size()
{
return _con.Size();
}

template<class T,template<class> class Container  = Seqlist>
T& Top()
{
size_t size = Size();
assert(size > 0);
return _con[size - 1];
}

template<class T,template<class> class Container  = Seqlist>
void print()
{
_con.Print();
}

template<class T,template<class> class Container  = Seqlist>
T& operator[](size_t index)
{
return _con[index];
}

  類模板的分離模式就會牽扯出一些問題,比如說編譯器在構造對象的時候它怎么找函數的定義的,因為函數的定義是在.cpp文件中的。這就是類模板的分離編譯問題

  假設我們stack類是放在stack.h中的,成員函數的定義放在stack.cpp中的,然后類的調用放在main.cpp中,并且在main.cpp中包含了stack.h。

 按照我們通常的思路

  • 編譯main.cpp時,編譯器不知道f(f是成員函數中的任意一個函數)的實現,所以當碰到對它的調用時只是給出一個指示,指示連接器應該為它尋找f的實現體。這也就是說main.obj中沒有關于f的任何一行二進制代碼。

  • 編譯test.cpp時,編譯器找到了f的實現。于是乎f的實現(二進制代碼)出現在test.obj里。 

  • 連接時,連接器在test.obj中找到f的實現代碼(二進制)的地址(通過符號導出表)。然后將main.obj中懸而未決的call XXX地址改成f實際的地址,pofect。

 

但是當你編譯的時候,編譯器就會報鏈接錯誤,找不到成員函數的定義。說明我們的思路是錯誤的。對于模板,在沒有實例化出對象之前是不會被編譯成二進制代碼的,而實例化是在程序運行的時候(也就是用到模板的時候)才實例化出對象,實例化是在編譯器對代碼進行編譯的后面才發生的。這樣問題就迎刃而解了,我們得手動的在main中包含.cpp文件,讓編譯器知道有函數的定義,這樣編譯器就不會報錯了。


這里有必要提醒(總結)一下的是

  • 如果你的類不是用模板實現的,就不會有分離編譯的問題,也就是說,即使你的類的成員函數是在類外定義的也不用include .cpp文件,不管你用沒用到都會實例化出代碼出來,就會編譯成二進制文件,在鏈接時就會鏈接起來

  • 如果你的類是模板類,并且想要在類外定義成員函數,就必須include .cpp文件。


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

临沧市| 井冈山市| 津市市| 耒阳市| 上饶县| 芜湖市| 黑龙江省| 石台县| 广平县| 舞阳县| 安泽县| 三台县| 旬邑县| 涿鹿县| 喀喇沁旗| 彭山县| 平利县| 顺平县| 上饶市| 南召县| 山东省| 淮滨县| 昌乐县| 白水县| 阆中市| 汶上县| 柏乡县| 子长县| 新余市| 环江| 习水县| 营山县| 阿荣旗| 三亚市| 台山市| 长治市| 宜州市| 西贡区| 永吉县| 廉江市| 银川市|