一、函数模版
1. 模版概述
函数模板:形参的类型不具体指定,用通用类型代替,在调用时,编译器会根据实参的类型推导出形参的类型(类型参数化)
//函数模板来实现
template <class T>//定义一个模板 模板的通用类型为T
//紧跟函数的定义
void swap_temp(T &a, T &b)
{
T temp = a;
a = b;
b = temp;
}
void test03()
{
char a = 1;
char b = 2;
int c = 3;
int d = 4;
swap_temp(a, b);//自动推导
swap_temp<char>(a, b);//显示指定类型
//swap_temp(a,c); 自动类型推导的结果不一致
swap_temp(c, d);
}
2. 函数模版和普通函数区别
函数模版:不能进行自动类型转换
普通函数:可以进行自动类型转换
3. 函数模板和普通函数在一起的调用规则
- c++编译器优先考虑普通函数
- 可以通过空模板实参列表的语法限定编译器只能通过模板匹配
- 函数模板可以像普通函数那样可以被重载
- 函数模板如果有更好的匹配,优先使用函数模板
4. 函数模版剖析
4.1 编译过程
4.2 函数模版的本质
本质是进行二次编译:第一次对函数模板进行编译,
第二次在调用处对函数模板展开,进行二次编译
二、类模版
1. 类模版形式
template <class T1, class T2>
2. 类模版作为函数参数
类模板作为函数的形参,该函数需要写成函数模板
template <class T1,class T2>
void show(Animal<T1, T2> &p)
{
//类模版不能自动推导
}
template <class T1>
void show1(T1 &p)
{
cout << p.age << " " << p.data << endl;30
}
3. 类模版遇到继承
在继承时,继承的类必须是一个模板类<>
类模板遇到继承,可以将子类写成类模板
template <class T>
class Base
{
public:
Base(T a)
{
this->a = a;
}
T a;
};
template <class T1,class T2>
class Son2 :public Base<T2>
{
public:
Son2( T1 x1,T2 a):Base<T2>(a), x(x1)
{]}
T1 x;
};
4. 成员函数在类内实现
template <class T1,class T2>
class Person
{
public:
Person(T1 a, T2 b)
{
this->a = a;
this->b = b;
}
void show()
{
cout << a <<" "<< b << endl;
}
T1 a;
T2 b;
};
5. 成员函数在类外实现
class Person
{
public:
Person(T1 a, T2 b);
void show();
T1 a;
T2 b;
};
//类模板的成员函数在类外实现 需要写成函数模板
template <class T1, class T2>
Person<T1,T2>::Person(T1 a, T2 b)
{
this->a = a;
this->b = b;
}
template <class T1, class T2>
void Person<T1, T2>::show()
{
cout << a << " " << b << endl;
}
6. 类模版成员函数的创建时机
类模板成员函数的创建时机是在调用时,没有调用,编译器不会创建这个函数,只有函数的声明
7. 类模版分文件问题
注意: 类模板的分文件,必须将函数的定义和类的声明写到一个文件
.hpp文件
template <class T1,class T2>
class person
{
public:
person(T1 a, T2 b);
void show();
T1 a;
T2 b;
};
template <class T1, class T2>
person<T1, T2>::person(T1 a, T2 b)
{
this->a = a;
this->b = b;
}
template <class T1, class T2>
void person<T1, T2>::show()
{
cout << a << " " << b << endl;
}
.cpp文件
#include "09person.hpp"
int main()
{
//调用构造函数和show函数需要创建,但是没有这两个函数的定义,不能创建
person<int, int> p(10, 20);//
p.show();
return 0;
}
8. 类模版遇到友元函数
template <class T1, class T2>
class Person;
//类模板作为函数形参,函数需要写成函数模板
template <class T1, class T2>
void showPerson(Person<T1, T2> &p)
{
cout << p.a << " " << p.b << endl;
}
template <class T1,class T2>
class Person
{
friend void showPerson<>(Person<T1, T2>& p);
friend void showPerson2(Person<T1, T2>& p)//定义一个全局函数并且声明为类的友元
{
cout << p.a << " " << p.b << endl;
}
public:
Person(T1 a, T2 b)
{
this->a = a;
this->b = b;
}
private:
T1 a;
T2 b;
};
void test01()
{
Person<int, string> p(100,"bobo");
showPerson(p);
}