C++模板函数

目录

一、模板函数

1.概念

2.一般模板函数

 3.特化模板函数

二、模板类

1.概念

2.模板类(Queue,Stack)

2.1Queue

2.2Stack

3.成员模板函数 

3.模板类特化

3.1全特化

3.2偏特化

三、模板类AutoPtr

 1.构造函数

2.析构函数

3.拷贝构造函数

4.等号、->、*等运算符重载

5.主函数调用AutoPtr


一、模板函数

1.概念

        模板函数不是一个实在的函数,编译器不能为其生成可执行代码。定义模板函数后只是一个对函数功能框架的描述,当它具体执行时,将根据传递的实际参数决定其功能。

2.一般模板函数

        以一个简单的Swap函数为例,其功能为交换两个变量的值。

void Swap(int & x, int & y)
{
    int tmp = x;
    x = y;
    y = tmp;
}

        上面的代码能实现交换功能,但是只能交换整数型即int类型,那么如果要交换浮点型或者字符型又需要另外写以下代码。

//浮点型
void Swap(double & x, double & y)
{
    int tmp = x;
    x = y;
    y = tmp;
}
//字符型
void Swap(char & x, char & y)
{
    int tmp = x;
    x = y;
    y = tmp;
}

        为了减少我们的代码量,此时就可以使用模板函数。所谓“模板”,就是可以用一个模子做出多种类似的东西,那么模板函数就是可以用一个函数实现对多种类型值的操作。

        模板函数写法如下:

template 
返回值类型  模板名(形参表)
{
    函数体
}

        还是以Swap函数为例,实现代码为:

#include 
using namespace std;
template
void Swap(T & x, T & y)
{
    T tmp = x;
    x = y;
    y = tmp;
}
int main()
{
    int n = 2, m = 8;
    Swap(n, m);  //编译器自动生成 void Swap (int &, int &)函数
    cout<<"n="<C++模板函数_第1张图片

 3.特化模板函数

        尽管模板函数能够对多种类型值进行操作,但是不同类型值在有些操作时需要先进行一定处理即特化,比如字符型是无法直接进行大小比较的,但我们可以比较其字符串长短,下面我们以Compare函数为例。

#include 
#include 
using namespace std;
//函数模板
template
bool Compare(T t1,T t2){
    return t1==t2;
}

template<> //函数模板特化
bool Compare(char *t1,char *t2){
    return strcmp(t1,t2)==0;
}

int main(int argc, char* argv[])
{
    int a = 2;
    int b = 2;
    int c = 8;
    double d = 2.8;
    double e = 2.8;
    double f = 8.2;
	char str1[] = "abc";
    char str2[] = "abc";
    char str3[] = "def";
    cout<

        如果类型值相等输出为1,反之则输出为0。运行截图如下:

C++模板函数_第2张图片

         可见经过特化之后的Compare函数除了能对数值进行大小比较还可以对字符型进行比较操作。需要注意的是模板函数只有全特化,没有偏特化。

二、模板类

1.概念

        一个类模板(类生成类)允许用户为类定义个一种模式,使得类中的某些数据成员、默认成员函数的参数,某些成员函数的返回值,能够取任意类型(包括系统预定义的和用户自定义的)。

        如果一个类中的数据成员的数据类型不能确定,或者是某个成员函数的参数或返回值的类型不能确定,就可以将此类声明为模板,它的存在不是代表一个具体的、实际的类,而是代表一类 类。

2.模板类(Queue,Stack)

       模板类的作用和模板函数的相同,都是为了减少代码量方便操作,这里就不再赘述。

       模板类的写法:

template  <类型形参表>
 class  <类名>
 {     //类说明体  };
 template  <类型形参表>
 <返回类型> <类名> <类型名表>::<成员函数1>(形参表)
 {     //成员函数定义体  }
 template  <类型形参表>
 <返回类型> <类名> <类型名表>::<成员函数2>(形参表)
 {     //成员函数定义体  }
 …
 template  <类型形参表>
 <返回类型> <类名> <类型名表>::<成员函数n>(形参表)
 {     //成员函数定义体  }

        在C++标准库(STL)中有栈和队列的类模板,因此可以直接使用。

2.1Queue

        队列的特点:先进先出,只能对队头和队尾的元素进行操作。

        queue的函数组成主要有:

                queue.size():返回队列中元素个数;

                queue.push():会将一个元素置入queue中;

                queue.front():会返回queue内的第一个元素(也就是第一个被置入的元素);

                queue.back():会返回queue中的最后一个元素(也就是最后被插入的元素);

                queue.pop():会移除queue内的第一个元素(也就是第一个被置入的元素);

        使用队列,要先包含头文件 : #include

#include  
#include 
using namespace std;
int main(){
	
	queue queue;
	int num;
	
	cout<<"入队:"; 
	
	for(int i = 1;i<10;i++){
		
		queue.push(i);
		cout<

运行截图:

C++模板函数_第3张图片

2.2Stack

        栈的特点:先进后出,只能对栈顶的元素进行操作。

        stack的函数组成主要有:

                stack.push():往栈头添加元素;
                stack.pop():从栈头移除第一个元素;
                stack.top():返回栈顶元素;
                stack.empty():判断堆栈是否为空,栈空返回true,栈非空返回false;
                stack.size():返回堆栈的大小;

        使用栈之前,要先包含头文件 : #include

#include  
#include 
using namespace std;
int main(){
	
	stack stack;
	int num;
	
	cout<<"入栈:"; 
	
	for(int i = 1;i<10;i++){
		cout<

运行截图:

C++模板函数_第4张图片

3.成员模板函数 

        成员模板函数在使用时有以下需要注意的地方:

        普通类的成员函数模板不管是普通类还是模板类,成员函数都可以是函数模板,称为“成员函数模板”,但不可以是虚函数,否则编译器报错。
        类模板的模板参数必须用<>指定,成员函数模板(函数模板)的模板参数可以自动推导。
        类模板的成员函数(普通成员函数/函数模板)只有为程序所用时(代码对函数或函数模板进行调用时)才实例化。 如果某函数从未使用,则不会实例化该函数。

//普通类
class A{
public:
	template     //成员函数模板
	void myfunc(T tempVal)
	cout << tempval <
class A{
public:
	template 
	A(T2 v1, T2 v2){
							//构造函数模板
	}					
	
	template      //成员函数模板
	void myfunc(T tempVal)
	cout << tempval < a(1,2);        //类模板的模板参数必须指定,函数模板自动推导。
A a(1.1, 2.2); 
a.myfpt();  			//调用时,才实例化该函数

成员函数外部实现
	
	template		//先跟类模板的模板函数列表
	template 		//构造函数自己的模板函数列表
	A::A(T2 v1, T2 v2){
		cout << v1 << v2 << endl;		//构造函数模板
	}

3.模板类特化

        模板函数特化和模板类特化的区别:模板函数只能全特化,而模板类既有全特化又有偏特化。

3.1全特化

        全特化即对所有模板类型都进行特化。

#include 
using namespace std;

template
class A{
        public:
                void function(T1 value1, T2 value2){
                        cout<<"value1 = "<C++模板函数_第5张图片

3.2偏特化

        偏特化即对模板类型做一些限制特化。

#include 
using namespace std;

template
class A{
        public:
                void function(T1 value1, T2 value2){
                        cout<<"value1 = "<C++模板函数_第6张图片

三、模板类AutoPtr

 1.构造函数

template
AutoPtr::AutoPtr(T* pData)
{
	m_pData = pData;
	m_nUser = new int(1);
}

2.析构函数

~AutoPtr()
	{
		decrUser();
	}
void decrUser();
template
void AutoPtr::decrUser()
{
	--(*m_nUser);
	if ((*m_nUser) == 0)
	{
		delete m_pData;
		m_pData = 0;
		delete m_nUser;
		m_nUser = 0;
	}
}

3.拷贝构造函数

template
AutoPtr::AutoPtr(const AutoPtr& h)
{
	m_pData = h.m_pData;
	m_nUser = h.m_nUser;
	(*m_nUser)++;
}

4.等号、->、*等运算符重载

AutoPtr& operator=(const AutoPtr& h);
T* operator->()
{
	return m_pData;
}
T& operator*()
{
	return *m_pData;
}
const T& operator *()const
{
	return *m_pData;
}
const T* operator ->()const
{
	return m_pData;
}
template
AutoPtr& AutoPtr::operator=(const AutoPtr& h)
{
	decrUser();
	m_pData = h.m_pData;
	m_nUser = h.m_nUser;
	(*m_nUser)++;
}

5.主函数调用AutoPtr

#include
#include 
#include "autoptr.h"
#include "CMatrix.h"
using namespace std;
int main()
{
    AutoPtr h1;
    double data[6] = {1,2,3,4,5,6};
    h1->Create(2,3,data);
    cout << *h1 << endl;
    AutoPtr h2(h1);
    (*h2).Set(0,1,10);
    cout << *h1 << endl << *h2;
}

运行截图:

C++模板函数_第7张图片

你可能感兴趣的:(c++)