模板

模板是泛型編程的基礎,即與類型無關的邏輯代碼。

利用模板機制可以顯著減少冗餘信息,能大幅度地節約程序代碼,進一步提高面向對象程序的可重用性和可維護性。

模板是實現代碼重用機制的一種工具,它可以實現類型參數化;

模板分爲函數模板和類模板。

爲了使用函數名相同,參數不同,返回值可同可不同的函數時,我們起初用了重載的方式。

#include<iostream>
using namespace std;

int add(int a,int b)
{
	return a+b;
}

double add(double a,double b)
{
	return a+b;
}

int main()
{
	cout<<"ret1="<<add(1,2)<<endl;
	cout<<"ret2="<<add(2.3,3.0)<<endl;
	getchar();
	return 0;
}

wKioL1bvstuDo-moAAAPLD_E0cI751.png

但是運用重載的方式寫起來比較不方便,尤其是重載的函數較多時,爲了解決這類問題,我們用函數模板來實現這種功能。

#include<iostream>
using namespace std;
template <class T>
T add(const T& a,const T& b)
{
        cout<<"type:"<<typeid(a).name()<<endl;   //顯示類型
	return a+b;
}

int main()
{
	cout<<"ret1="<<add(1,2)<<endl;//還可以顯示實例化,顯示指定T爲int,即add<int>(1,2)
	cout<<"ret2="<<add(2.3,3.0)<<endl;   //add<double>(2.3,3.0)
	getchar();
	return 0;
}

wKioL1bvt4bxX-QPAAARBJCMVr0319.png

以上函數中函數參數類型都是相同的,當我們遇到形如:add(1,2.3);一個參數爲int,一個參數爲double型,此時我們可以這樣定義:

template <class T1,class T2>
T add(const T1& a,const T2& b)
{
	return a+b;
}

當然,肯定有人會想,模板函數可以構成重載嗎?    j_0057.gif答案是肯定的。

#include<iostream>
using namespace std;

int add(int a,int b)
{
	return a+b;
}

double add(double a,double b)
{
	return a+b;
}
template <class T>
T add(const T& a,const T& b)
{
	cout<<"type:"<<typeid(a).name()<<endl; 
	return a+b;
}

int main()
{
	cout<<"ret1="<<add(1,2)<<endl;
	cout<<"ret2="<<add(2.3,3.0)<<endl;
	getchar();
	return 0;
}

當模板構成重載,調用add的函數時,它會先調用非模板類的函數,性能比較高;而模板函數內部還得調用,有推演過程判斷它是什麼類型,效率上會有所降低。


2.模板類

對於普通函數來說,我們拿typedef重定義一個類型,當需要改的時候,需要將int改掉就可以了;

typedef int DataType;
 class SEQLIST
{
private:
    DataType *data;
};

而我們爲了適應更多的類型,於是引入了模板類,我們這樣定義,體現了其高度複用的優勢:

template<class T>
class SeqList
{
private:
    T* data;
};

寫一個模板類實現SeqList的動態順序表吧:

#include<iostream>
using namespace std;

template <class T>
class SeqList
{
public:
	SeqList()
		:_data(NULL)
		,_size(0)
		,_capacity(0)
	{}
	SeqList(const SeqList<T>& s);
	SeqList<T>& operator=(const SeqList<T>& s);
	~SeqList()
	{
		if(_data != NULL)
		{
			delete[] _data;
		}
	}
	void CheckCapacity();
	void PushBack(const T& d);
	void PopBack();
	void PushFront(const T& d);
	void PopFront();
	void Print();
private:
	T *_data;
	int _size;
	int _capacity;
};
template <class T>
SeqList<T>::SeqList(const SeqList<T>& s)
{
	_data = new T[s._size*sizeof(T)];
	int i = 0;
	for(i = 0;i < s._size; i++)
	{
		_data[i] = s._data[i];
	}
	_size = s._size;
	_capacity = s._capacity;
}
template <class T>
SeqList<T>& SeqList<T>::operator=(const SeqList<T>& s)
{
	int i = 0;
	if(this == &s)
	{
		return *this;
	}
	_size = s._size;
	_capacity = s._capacity;
	delete _data;
	_data = new T[_capacity];
	for(i = 0; i < _size; i++)
	{
		_data[i] = s._data[i];
	}
	return *this;
}
template <class T>
void SeqList<T>::CheckCapacity()
{
	if(_size == _capacity)
	{
		T* tmp = new T[_capacity*2+3];
		//memcpy(tmp,_data,_size*sizeof(T));
		int i = 0;
		for(i = 0; i < _size; i++)
		{
			tmp[i] = _data[i];
		}
		delete[] _data;
		_data = tmp;
		_capacity = _capacity*2+3;
	}
}
template <class T>
void SeqList<T>::PushBack(const T& d)
{
	CheckCapacity();
	_data[_size] = d;
	_size++;
}
template <class T>
void SeqList<T>::PopBack()
{
	CheckCapacity();
	_size--;
}

template <class T>	
void SeqList<T>::PushFront(const T& d)
{
	int i ;
	CheckCapacity();	
	for(i = _size; i > 0; i--)
	{
		_data[i] = _data[i-1];
	}
	_data[0] = d;
	_size++;
}

template <class T>
void SeqList<T>::PopFront()
{
	int i;
	CheckCapacity();
	for(i = 0; i < _size; i++)
	{
		_data[i] = _data[i+1];
	}
	_size--;
}
template <class T>
void SeqList<T>::Print()
{
	int i = 0;
	for(i = 0; i < _size; i++)
	{
		cout<<_data[i]<<" ";
	}
	cout<<endl;
}

int main()
{
	SeqList<int> seq;
	SeqList<int> seq1;
	cout<<"seq:"<<endl;
	cout<<"尾插1234"<<endl;
	seq.PushBack(1);
	seq.PushBack(2);
	seq.PushBack(3);
	seq.PushBack(4);
	seq.Print();
	cout<<"尾刪"<<endl;
	seq.PopBack();
	seq.Print();
	cout<<"頭刪"<<endl;
	seq.PopFront();
	seq.Print();
	cout<<"seq2:"<<endl;
	SeqList<int> seq2(seq);
	seq2.Print();
	cout<<"頭插567"<<endl;
	seq.PushFront(5);
	seq.PushFront(6);
	seq.PushFront(7);
	seq.Print();
	seq1 = seq;
	cout<<"seq1:"<<endl;
	seq1.Print();
	getchar();
	return 0;
}

wKiom1byIpvxh_K5AAAVEIOLwCM902.png

模板就說到這裏啦,有好的建議還希望大家提出來,歡迎來訪哦。i_f01.gifi_f01.gif

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