(一)模板特点:
模板只是一个框架,不可以直接使用
模板不是万能的
(二)泛型编程
函数模板和类模板
template <typename T>
函数声明或定义
//typename可以用class代替
把数据类型抽象成参数
#include <iostream>
using namespace std;
template <typename T>
void mySwap(T &a,T &b)
{
T temp=a;
a=b;
b=temp;
}
int main()
{
int a=1;
int b=66;
mySwap(a,b);
cout<<a<<endl;
cout<<b<<endl;
mySwap<int>(a,b);
cout<<a<<endl;
cout<<b<<endl;
}
输出
lv@lv-HP:~/learning_c++$ ./33模板
66
1
1
66
(三)注意事项
自动类型推导,必须推导出一致的数据类型T才可以使用
模板必须确定出数据类型T才可以使用
(四)普通函数与函数模板的区别
- 普通函数调用时可以发生自动类型转换(隐式类型转换)
- 函数模板调用时,如果利用自动类型推导,不会发生隐式类型转换
- 函数模板调用时,如果利用显示指定的方式,可以发生隐式类型转换
(五)普通函数与函数模板的调用规则
- 如果函数模板和普通函数都能调用,优先使用普通函数
- 空模板参数列表来强制调用参数模板
- 函数模板也可以发生重载
- 如果函数模板可以产生更好的匹配,优先使用函数模板
#include <iostream>
using namespace std;
void test(int a,int b)
{
cout<<"普通函数"<<endl;
}
template <typename T>
void test(T a,T b)
{
cout<<"模板函数"<<endl;
}
int main()
{
int a=10;
int b=20;
test(a,b);
char c='c';
char v='v';
test(c,v);
return 0;
}
输出
lv@lv-HP:~/learning_c++$ ./36模板(2)
普通函数
模板函数
(六)模板的局限性
模板的通用功能不是万能的
利用具体化模板,可以解决自定义类型的通用
(七)类模板
1.类模板基本语法
template <typename T>
类
//typename可以用class代替
#include <iostream>
using namespace std;
template<class NameType,class AgeType>
class Person
{
public:
Person(NameType a,AgeType b)
{
this->Name=a;
this->Age=b;
}
NameType Name;
AgeType Age;
};
int main()
{
Person<string,int> p1("lvwencheng",20);
cout<<p1.Age<<endl;
cout<<p1.Name<<endl;
}
输出
lv@lv-HP:~/learning_c++$ ./37模板(3)
20
lvwencheng
2.类模板与函数模板区别
- 类模板没有自动类型推导的适用方式
- 类模板在模板参数列表中可以有默认参数
template<class NameType,class AgeType=int>
3.类模板中成员函数创建的时机
普通类的成员函数一开始就创建
类模板的成员函数在调用时才创建
4.类模板对象做函数参数(很重要)
指定传入的类型
参数模板化
类模板化
5.类模板与继承
- 父类是个类模板时,子类在声明时要指出父类中T的类型
- 如果不指定,编辑器无法给子类分配内存
- 如果想更灵活,子类也要变成类模板
#include <iostream>
using namespace std;
template<class T>
class Base
{
public:
T father_name;
};
class Son:public Base<int>
{
};
template<class T1,class T2>
class Son2:public Base<T1>
{
public:
T2 son_name;
};
int main()
{
Son2<string,string> s;
s.father_name="123";
s.son_name="456";
return 0;
}
6.类模板成员函数类外实现
7.类模板分文件编写
8.类模板与友元
(八)C++引用
-
基本语法:
数据类型 &别名=原名 -
注意事项:
引用必须初始化
引用初始化之后,不可以改变 -
引用做函数参数
#include <iostream>
using namespace std;
//1.值传递
void swap1(int a,int b)
{
int temp=a;
a=b;
b=temp;
}
//2.地址传递
void swap2(int *a,int *b)
{
int temp=*a;
*a=*b;
*b=temp;
}
//3.引用做函数参数
void swap3(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
}
int main()
{
int a=50;
int b=100;
swap1(a,b);
cout<<a<<endl;
cout<<b<<endl;
swap2(&a,&b);
cout<<a<<endl;
cout<<b<<endl;
swap3(a,b);
cout<<a<<endl;
cout<<b<<endl;
}
输出
lv@lv-HP:~/learning_c++$ ./34C++引用
50
100
100
50
50
100
- 引用做函数返回值
不要返回局部变量的引用
函数调用可以作为左值
#include <iostream>
using namespace std;
int& test()
{
static int a=10;
return a;
}
int main()
{
int &ref=test();
cout<<ref<<endl;
cout<<ref<<endl;
test()=1000;
cout<<ref<<endl;
cout<<ref<<endl;
return 0;
}
输出
lv@lv-HP:~/learning_c++$ ./35C++引用(2)
10
10
1000
1000
- 引用的实质就是一个指针常量
int &ref=a;
int* const ref=&a;
- 常量引用,防止形参改变实参