C++ 模板
C++另一种编程思想称为泛型编程,主要利用的技术就是模板。
C++提供了两种模板机制:函数模板和类模板。
函数模板
作用:建立一个通用函数,其函数返回值类型可以不具体的制定,用一个虚拟的类型来代表。
语法:
template<typename T>
函数
template------声明创建模板
typename------表明后面的符号是一种数据类型,可以用class代替
T------通用的数据类型,名称可以替换,通常为大写字母
两种方式使用模板函数:自动类型推导和显示指定类型
自动类型推导:在使用模板时不需要写参数类型,可根据参数定义自动确定数据类型
显示指定类型:在使用模板时需要在参数前面<>内写数据类型
例子:
//用模板实现两个数的交换,可以交换int 型和double型
#include<iostream>
#include<string>
using namespace std;
template<typename T>
void myswap(T &a,T &b)
{
T temp = a;
a = b;
b = temp;
}
void fun1()
{
int a = 6;
int b = 9;
double c = 1;
double d = 2;
myswap(a, b);//自动类型推导
myswap<int>(a,b);//显示指定类型
myswap(c, d);//自动类型推导
myswap<double>(c, d);//显示指定类型
cout << "a=" << a << endl;
cout << "b=" << b << endl;
cout << "c=" << c << endl;
cout << "d=" << d << endl;
}
int main()
{
fun1();
return 0;
}
注意:在使用模板时,要保证模板的参数类型要一致。
如果参数的数据类型是自定义的person类的数据类型,该怎么办呢?
答:可以利用模板的重载,可以为这特定的类型提供具体化的模板。
例子:
#include<iostream>
#include<string>
using namespace std;
class person
{
public:
person(string name,int age)
{
m_name = name;
m_age = age;
}
string m_name;
int m_age;
};
template<typename T>
bool mycompare(T &a, T &b)
{
if (a==b)
{
return true;
}
else
{
return false;
}
}
template<> bool mycompare(person &p1, person &p2)
{
if (p1.m_name==p2.m_name && p1.m_age==p2.m_age)
{
return true;
}
else
{
return false;
}
}
void fun()
{
person p1("Tom",10);
person p2("Tom",10);
bool ret = mycompare(p1,p2);
if (ret)
{
cout << "p1=p2" << endl;
}
else
{
cout << "p1!=p2" << endl;
}
}
int main()
{
fun();
return 0;
}
类模板
作用:建立一个通用类,其类成员数据类型可以不具体的制定,用一个虚拟的类型来代表。
语法:
template<typename T>
类
类模板中的成员函数是在调用时才被创建的,
类模板对象做函数参数
有三种形式:
- 1.指定传入类型
- 2.参数模板化
- 3.整个类模板化
例子:
#include<iostream>
#include<string>
using namespace std;
template<class T1,class T2>
class person
{
public:
person(T1 name,T2 age)
{
this->m_name = name;
this->m_age = age;
}
void myprint()
{
cout << "姓名: " << m_name << " 年龄: " <<m_age<< endl;
}
T1 m_name;
T2 m_age;
};
1.指定传入类型(较为常用)
void work1(person<string,int> &p)
{
p.myprint();
}
2.参数模板化
template<class T3,class T4>
void work2(person<T3,T4> &p)
{
p.myprint();
}
3.整个类模板化
template<class T5>
void work3(T5 &p)
{
p.myprint();
}
类模板与继承
继承有二种形式:
- 1.子类继承的父类是模板时,在继承时一定要指定T类型
- 子列继承的父类是模板时,如果想灵活指定父类中的T类型,子类也需要模板化
例子:
#include<iostream>
#include<string>
using namespace std;
template<class T>
class base
{
public :
T m;
};
1.子类继承的父类是模板时,在继承时一定要指定T类型
class son1 :public base<int>
{
public:
};
2.子列继承的父类是模板时,如果想灵活指定父类中的T类型,子类也需要模板化
template<class T1>
class son2 :public base<T1>
{
public:
son2(T1 m)
{
this->m = m;
}
void myprint()
{
cout << "姓名: " << this->m << endl;
}
};
类成员函数类外实现
在类外实现时:
template<class T1,class T2>
person<T1,T2>::person(T1 name,T2 age)
{
this->m_name = name;
this->m_age = age;
}
函数名前面一定要加带有通用数据类型的类名(person<T1,T2>),如果不加通用数据类型,则是错误的;因为此类是模板类,不加通用数据类型则是普通类。
类模板分文件编写
问题:类模板中的成员函数是在调用时才被创建的,导致分文件编写时链接不到
解决方法:
- main文件中直接包含“。cpp”文件
- 将声明和实现写在同一文件中,并更改后缀名为“.hpp”。
类模板与友元
友元函数有两种实现方式:类内和类外
类外在实现时比较麻烦,所以尽量使用类内实现函数友元。类内实现和普通的友元实现一样。