c++11模板用法

1.1 简介

1、简介

C++提供了两种模板机制,函数模板和类模板

使用范围:模板的声明或定义只能在全局或类范围进行,不能在局部范围(如函数)内进行。

使用目的:使用模板是为了能够让程序员编写与类型无关的代码

函数模板和模板函数区别:函数模板是一个模板,其中用到通用类型参数,不能直接执行;模板函数是一个具体的函数,它是一个具体执行的函数,由编译系统在遇到具体函数调用时生成,可执行。

1.2 函数模板

1、函数模板格式

template <类型形参表或称模板参数列表> //类型函数声明

返回类型 函数名(形参表)

{

函数体;

}

注意:

模板参数表:定义在类或函数定义中用到的类型或值。

类型形参表:可以包含基本数据类型,也可以包含类类型。类型形参需要加class或typename关键字(两者等价)

类型形参表的参数必需是唯一的,不能有重名的。

template声明语句和函数模板声明之间不允许有其他语句。

2、函数模板实例化为模板函数

函数模板不能直接执行需要实例化为模板函数后才能执行。

编译系统发现有一个函数调用“函数名(实参表)”或“函数名<类型实参表>(实参表)”时,c++将根据“实参表”中的类型生成一个重载函数,即模板函数。

举例:

函数模板:

template <class T> //T 的名字也为其他 T abs(T x) { if (x < 0) return -x; return x; }

//调用函数模板生成模板函数

cout << abs(-1) << endl;//输出结果为1

生成的模板函数如下:

int abs(int x)

{

if(x<0) return -x;

return x;

}

3、函数模板本身可以重载

1.3 类模板

1、简介

类模板允许用户为类定义一种模式,使得类中的某些数据成员、成员函数的参数或成员函数的返回值能取任意类型。类模板的成员函数被认为是函数模板。

 

2、定义类模板格式

template <类型形参表> //类型参数声明

class 类名

{

类模板的代码

}

template<类型形参表> //定义在类模板之外的函数必需以关键字template开始

返回类型 类名 类型名表::成员函数n(形参表)

{

成员函数定义体

}

3、实例化类模板

类模板不能直接使用,必需先实例化为相应的模板类。定义类模板之后,创建模板类的格式如下:

类模板名 <类型实参表> 对象表;

类型实参表与类模板中的类型形参表相匹配。

4、类模板举例

#include <iostream>
#include <map>
#include "string"

//#include <memory>

using namespace std;
template <typename T>
class Array  //类模板
{
	int size;
	T *p;
public:
	Array();//默认构造函数
	Array(int n);//重载构造函数
	T &operator[](int) const;//[]重载函数
};

//默认构造函数
template <typename T>
Array<T>::Array()
{
	size = 10;
	p = new T[size];
}

//重载构造函数
template <typename T>
Array<T>::Array(int n)
{
	size = n;
	p = new T[size];
}
//下标运算符重载函数
template<typename T>
T &Array<T>::operator[](int i)const 
{
	if (i >= 0 && i < size)
	{
		return p[i];
	}
}

class Student
{
	int no;
	char name[10];
public:
	Student() {}
	Student(int n,const char *s)//注意要有const 否则”Tom“无法传参
	{
		no = n;
		strcpy_s(name, s);//使用strcpy 为字符串数组赋值
	}
	Student &operator=(Student &s) //赋值重载构造函数
	{
		no = s.no;
		strcpy_s(name, s.name);
		return *this;
	}
	void display()
	{
		cout << "学号:" << no << ",姓名:" << name << endl;
	}
};

int main()
{
	Array<int> a(5);
	for (int i=0;i<5;i++)
	{
		a[i]=i+1;//调用运算符重载函数
		cout << a[i] << " ";
	}
	cout << endl;
	cout << "学生列表" << endl;
	Array<Student> b(3);
	//int c = 1;
	Student x(1, "Tom"), y(2, "Marry"), z(3, "John");
	b[0] = x; b[1] = y; b[2] = z;
	for (int i=0;i<3;i++)
	{
		b[i].display();
	}
}

 

 

 

5、类模板作为函数参数

//类模板

template <class T>  //T 的名字也为其他
class A
{
	T x;
public:
	A(T a) { x = a; }
	T abs()
	{
		if (x < 0) return -x;
		else return x;
	}
};

//函数模板中模板类作为形参

template <class T>
void fun(A<T> x)
{
	cout << x.abs() << endl;
}
int main()
{
	//建立对象
	A<int> s1(-5);
	A<double> s2(-5.8);
	fun(s1);
	fun(s2);

}

 

 

 

5、类模板中也可以使用非类型参数,即值参数

template<class T,int size>

class A

{

.....

}

实例化:

A<int,3> s;

 

6、模板与静态函数

类模板中定义静态函数,则该模板类的所有对象共享一个静态数据成员。

 

7、类模板的友元函数

一个类模板中可以设计友元函数,友元函数的形参可以是类模板或类模板的引用。如果在类模板中设计与参数类型无关的友元函数,那么在类外面实现时也不能省略template类型参数声明,否则将其看成是一个普通全局函数。

template <class T>  //T 的名字也为其他
class A
{
	
public:
	T x;
	A() {  }
	A(T i):x(i){  }
	friend void f1();//与参数类型无关的友元函数
	friend void f2(A<T> &);//与参数类型有关的友元函数
	
};
template<class T>
void f1(){ cout << "f1" << endl; }
template<class T>
void f2(A<T> &a) { cout << "f2:x " << a.x << endl; }

int main()
{
	A<double> a(1.2);
	f1<int>();//f1是模板类A<int>的友元函数
	f1<double>();//f1是模板类A<double>的友元函数
	f2<double>(a);//f2是模板类A<double>的友元函数
}

 

 

1.4 可变参数模板

1、概况

c++ 11 可变参数模板,对参数进行了高度泛化,能表示任意个数,任意类型的参数。

c++11 可变参数模板,就是一个接受可变数目参数的模板函数或模板类。可变数目的参数被称为参数包

存在两种 参数包:

模板参数包:表示0个或多个模板参数

函数参数包:表示0个或多个函数参数

2、格式

template<class... >

template<typename...>

举例:

#include <iostream>
#include <map>

//#include <memory>

using namespace std;
template <typename T,typename...Args>//foo是可变参数函数模板  有一个名为T的类型参数和一个名为Args的模板参数包
void foo(const T &t,const Args& ...rest)  //foo函数列表包含一个const&类型的参数 指向T的类型,名为rest的函数参数包
{
	cout << sizeof...(rest) << endl;//输出函数参数的数目
};

int main()
{
	int i = 0; double d = 3.14; string s = "hello";
	foo(i,s,42,d);//包中有三个参数
	foo(s, 42, d);//包中有两个参数
	foo(d, s);//包中有一个参数
	foo("hi");//空包
}

 

 

3、统计可变数目参数的个数

#include <iostream>

using namespace std;
template <class... T>
void f(T... args)
{
	cout << sizeof...(args) << endl;
};

int main()
{
	f();
	f(1, 2);
	f(1, 2.5, "");

}

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值