一、类模板
#include <iostream>
using namespace std;
template <typename T>class A
{
public:
A(T a)
{
this->a = a;
}
void show()
{
cout << "a = " << a << endl;
}
private:
T a;
};
// 模板类派生类
// 1、派生一个具体的类
class B:public A<int>
{
public:
B(int a, int b):A(a)
{
}
private:
int b;
};
// 2、派生一个模板类
template <typename T, typename T2>
class C:public A<T>
{
public:
C(T a, T2 c):A(a)
{
}
private:
T2 c;
};
template <typename T>
class D:public A<int>
{
public:
C(int a, T d):A(a)
{
}
private:
T d;
};
// 类模板对象作为函数参数传递
// 1、写一个确定具体的 模板类
void func(A<int> &a)
{
a.show();
}
void func(A<double> &a)
{
a.show();
}
// 2、写一个函数模板
template <typename T>
void func2(A<T> &a)
{
a.show();
}
int main()
{
// 类模板使用必须要指明类型
A<int> a(10);
// a.show();
// func(a);
func2(a);
A<double> d(1.2);
// d.show();
// func(d);
func2(d);
return 0;
}
二、类模板的使用之1
#include <iostream>
using namespace std;
// 所有函数都在类的内部实现包括友元函数
template <typename T>
class Complex
{
// 友元函数在类的内部实现,====> 但是它还是一个 友元函数(外部函数), 不是类的内部成员函数
friend ostream& operator<<(ostream& out, Complex<T> &c)
{
out << c.a << " + " << c.b << "i";
return out;
}
friend Complex Sub(Complex &c1, Complex &c2)
{
Complex tmp(c1.a - c2.a, c1.b - c2.b);
return tmp;
}
public:
Complex(T a = 0, T b = 0)
{
this->a = a;
this->b = b;
}
// 在类内部 <T> 可写可不写
Complex operator+(Complex &c)
{
Complex tmp(a + c.a, b + c.b);
return tmp;
}
private:
T a; // 实部
T b; // 虚部
};
int main()
{
Complex<int> c;
Complex<int> c1(1, 2), c2(3, 4);
c = c1 + c2;
cout << c << endl;
c = Sub(c1, c2);
cout << c << endl;
return 0;
}
三、类模板的使用之2
#include <iostream>
using namespace std;
// 2、普通函数作为类的友元函数:
// 2、2 类的声明
template <typename T>
class Complex;
// 2、1 进行函数声明
template <typename T>
Complex<T> Sub(Complex<T> &c1, Complex<T> &c2);
template <typename T>
class Complex
{
// 1、运算符重载的友元函数,需要在 函数名和形参列表之间加 <T>
friend ostream& operator<< <T>(ostream& out, Complex<T> &c);
// 2.3 在函数名和形参列表之间加 <T>
friend Complex<T> Sub <T>(Complex<T> &c1, Complex<T> &c2);
public:
Complex(T a = 0, T b = 0);
Complex operator+(Complex &c);
private:
T a; // 实部
T b; // 虚部
};
// 1、类模板的成员函数在类的外部实现,则所有函数都要写成函数模板形式
// 2、在表明该函数属于哪个类的时候,要在类名后面加 <T>
template <typename T>
Complex<T>::Complex(T a = 0, T b = 0)
{
this->a = a;
this->b = b;
}
// 3、函数的返回值一定要加上 <T>
template <typename T>
Complex<T> Complex<T>::operator+(Complex &c)
{
Complex tmp(a+c.a, b+c.b);
return tmp;
}
template <typename T>
ostream& operator<<(ostream& out, Complex<T> &c)
{
out << c.a << " + " << c.b << "i";
return out;
}
template <typename T>
Complex<T> Sub(Complex<T> &c1, Complex<T> &c2)
{
Complex<T> tmp(c1.a-c2.a, c1.b-c2.b);
return tmp;
}
int main()
{
Complex<int> c;
Complex<int> c1(1,2), c2(3,4);
c = c1 + c2;
cout << c << endl;
c = Sub(c1, c2);
cout << c << endl;
return 0;
}
四、类模板的使用
Ø 从类模板实例化的每个模板类有自己的类模板数据成员,该模板类的所有对象共享一个static数据成员
Ø 和非模板类的static数据成员一样,模板类的static数据成员也应该在文件范围定义和初始化
Ø 每个模板类有自己的类模板的static数据成员副本
注意:可以看到相同类型如int对应的类模板的对象之间的static成员是共享的,不同类型之间如int,float,char对应的类模板的对象之间的static是不共享的。