菜菜学C++之模板
一. 知识点梳理
1. 模板和泛型编程
1.1 模板和泛型编程概念
- 泛型编程是独立于任何特定的类型的方式编写代码
- 模板是泛型编程的基础,模板是创建类或者函数的蓝图或公式
1.2 函数模板
- 函数模板用来创建一个通用功能的函数,用来支持多种不同类型的形参,进一步简化重载函数的函数体设计
- 函数模板的定义
template <typename(class) T >
T min(T a, T b){
return a<b?a:b;
}
- 模板形参
1.类型形参T表示一个类型,表示哪个类型由编译器所调用的函数决定
2.非类型形参表示一个值 - 模板形参的作用域
模板形参的作用域为声明模板形参后直到模板声明或定义的末尾处,模板形参遵循名字屏蔽规则
- 模板形参名字限制
1.模板形参名字在同一模板参数表中只能被使用一次
2.在函数模板定义中声明的对象或类型不能与模板形参同名 - 非类型形参
template <class T, unsigned int N>
void array_int(T(&a)[N]){}
非类型形参N,在函数模板内部作为一个常量值,用来指定数组的长度
- 函数模板的实例化
1.函数模板不是一个可以直接执行的函数,根据实际情况使用形参的数据类型替代了模板类型之后才会生成函数
2.将模板形参实例化的参数称为模板实参,用模板实参实例化后生成的函数称为函数模板
3.函数模板在它被调用或用它对函数指针进行初始化或者赋值时实例化
1.3 函数模板实参推断
- 多个类型形参的实参必须完全匹配,如果不匹配,有以下两种方法解决
强制类型转换
函数模板中定义两个模板类型实参
- 类型形参的实参的受限转换
(1)const转换
模板形参为指向const对象的指针时,可以接受实参为指向非const对象的指针
模板形参为const引用时,可以接受实参为非const的引用
(2)数组或函数收到指针的转换
模板形参不是引用类型时,对数组或者函数类型的实参可以常规的转换为指针
- 非模板形参支持隐式类型转换
op2位非模板形参,支持隐式类型转换,实参d可以隐式转换为int型
const char *类型的s2不能隐式转换为int型
1.4 类模板
使用类模板使用户可以为类声明一种形式,使得类中的某些数据成员。某些成员函数的参数、某些成员函数的返回值能取任意类型。
- 类模板的定义
template <class T>
class Test{
private:
T data;
public:
T getData(){}
};
使用类模板时,必须为模板形参显式指定实参。
Test <int> t1;
Test <string> t2;
- 类模板成员函数
类内定义
template <class T>
class Test{
private:
T data;
public:
T getData(){}
T &operator =(const Test& other);
};
类模板外定义成员函数的方式:
template <class T>
T Test<T>::getData(){
return data;
}
template <class T>
Test& Test<T>::operator =(const Test<T> &other){
data = other.data;
return *this;
}
- 类模板的实例化
类模板每次实例化都会产生一个独立的类类型
Test t1;
Test t2;
以int实例化的模板类与以string型实例化的模板类没有关系,对它的成员也没特殊的访问权限
- 类模板在引用实际模板类类型时被实例化
1.定义模板类对象时
2.通过类指针或引用指向一个类模板实例时,只有当检查这个指针或引用指向的对象时(访问数据或成员函数),才会被实例化
3.当类模板被实例化时,类模板的成员函数并不自动被实例化,只有该函数被调用或取地址时,才被实例化
4.静态数据成员只有被使用时才被实例化 - 类模板的模板形参可以设置默认参数
template <class T = double, int N = 3>
class Test{
private:
T *pt;
public:
Test(){
pt = new T[N];
}
};
仅允许在类模板上使用默认模板参数,函数模板不允许。
- 类模板的静态成员
1.类模板的每个实例化的类都有自己的static成员
2.实例化的模板类的所有对象共享一个static成员
3.类模板的static数据成员同样要在类外部定义
template <class T>
class Test{
private:
static int data;
T a;
public:
static int count(){
return data;
}
};
- 类模板中的友元声明:
1.普通非模板类或函数的友元声明,将友元关系授予明确指定的类或函数
2.类模板或函数模板的友元声明,授予友元所有实例的访问权
3.只授予对类模板或函数模板的特定实例的访问权
二. 疑难点整理
1.函数模板与类模板的异同?
- 模板的实例化不同。函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化必须有程序员在程序中显示的指定。
- 函数模板允许重载,类模板不允许
- 函数模板仅支持全特化,而类模板可以进行全特化和偏特化
- 函数模板不支持模板默认参数,而类模板可以支持默认模板参数
2.类模板的所有实例化模板共享一个静态成员吗?
共享的,因为静态成员在程序编译阶段就已经确立好,所有共享