函数模板
类型参数化(形参为通用类型,由实参编译器自动推导出具体类型)
本质:在调用处推导出通用类型
实现:
template <class T> //定义一个模板,模板的通用类型为T,class也能变为typename
void swap (T &a, T &b)
{
T temp;
temp=a;
a=b;
b=temp;
}
// T只能推导出一个结果,即传入a,b的实参为同一类型
void test()
{
int x=1,y=2;
swap(x,y);
swap<int>(x,y); //也可不推导,直接给出通用类型的类型
}
有同名的普通函数时:
void test()
{
int a,b;
char c;
swap(a,b); //形参类型与普通函数匹配,优先调用普通函数,不用推导
swap<>(a,b); //指定调用函数模板
swap<int>(a,b); //同上
swap(a,c) //只能普通函数,普通函数的实参c可以自动类型转换,函数模板不能自动类型转换
swap(c,d) //形参类型与普通函数不匹配,优先调用函数模板
}
类模板
template <class T>
class Person
{
public:
Person(T a)
{
this->a =a;
}
T a;
};
void test()
{
//不能自动类型推导
Person<int> p(10); //指定显示法
Person<string> q("hello");
}
类模板作函数形参
void show( Person<int> &p) //实参只能传p,不能传q
{
cout<< p.a << endl;
}
//改为函数模板1
template <class T>
void show( Person<T> &p)
{
cout<< p.a << endl;
}
调用时
show<string>(q);
//改为函数模板2
template <class T>
void show( T &p)
{
cout<< p.a << endl;
}
调用时
show(q);
类模板遇到继承
template <class T>
class Base
{
public:
Base(T a)
{
this->a = a;
}
T a;
}
//继承的是指定类型的类模板
class Son : public Base<int>
{
public:
Son(int x1, int a) : Base<int> (a),x(x1)
{};
int x;
}
调用
Son p(1,2);
//继承的是通用类型的类模板
template< class T1, class T2>
class Son : public Base< T2>
{
public:
Son(T1 x1, T2 a) : Base<T2> (a),x(x1)
{};
T1 x;
}
调用:
Son<int, string> p(1,"hello");
类模板成员函数的类外实现
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;
}
void Person< T1,T2>::show()
{
cout<<a<<" "<<b<<endl;
}
类模板的成员函数创建时机:调用时(没调用,编译器不会创建,只有声明)
类模板的头文件和cpp文件分离
1. hpp (即有头文件也用函数定义)
类模板成员变量和成员函数(类外实现函数定义也要放在头文件(同个文件),写为类内实现更佳)
main.cpp
实例化对象再引用
类模板遇上友元
友元声明时要加上<>
例:
//类模板声明
template< class T>
class Person;
//全局函数
template<class T> //类模板作形参,用函数模板
void show( Person<T> &p)
{
cout<<p.a<<endl;
}
//类模板定义
template< class T>
class Person
{
//友元函数声明
friend void show<>(Person<T> &p);
public:
Person(T a)
{
this->a=a;
}
private:
T a;
}