什么是类模板?
模板的目的就是为了淡化数据类型的要求,作出通用数据类型的模板。类中的成员变量和成员函数都牵涉到了数据类型。
在成员函数、成员变量以及基类中包含有类型参数的类称为类模板。
和函数模板一样,类模板只是一个模板,并不是真正的类。
形式:template<class T1, class T2, ... ,class Tn>
class className
{ ... };
类模板与函数模板的异同
类模板和函数模板都需要二次编译
我们看到函数模板的原理是二次编译。同样的类模板也需要二次编译。
类模板 -- 实例化为 -> 类 -- 实例化为 -> 对象
类模板先在编译期的时候实例化为类,再在运行的时候实例化为真正的对象。其实类中的这个二次编译也叫二次实例化。
类不能隐式推断
我们在上一篇中讲到了函数模板的隐式推断,但是类模板却不能隐式推断。
class_template.cpp
#include <iostream>
using namespace std;
template <typename T> //声明
class Complex;
template <typename T>
ostream &operator << (ostream &out, const Complex<T> &c);
//模板类
template <typename T> //作用域很小
class Complex
{
friend ostream &operator << <T> (ostream &out, const Complex<T> &c);
//将该函数声明成模板函数
/*
friend ostream &operator << (ostream &out,const Complex<T> &c) //全局函数可以在类的内部实现
{
out << c.m_a << "+" << c.m_b << "i" ;
return out;
}
*/
private:
T m_a;
T m_b;
public:
Complex(T a, T b);
void print();
};
template <typename T>
Complex<T>::Complex(T a, T b) //函数放在外面需要在Complex后面加上<T>
{
m_a = a;
m_b = b;
}
template <typename T>
void Complex<T>::print()
{
cout << m_a << "+" << m_b << "i" << endl;
}
//该函数放在外面就要系很多声明
template <typename T>
ostream &operator << (ostream &out, const Complex<T> &c) //Complex是模板类
{
out << c.m_a << "+" << c.m_b << "i" ;
return out;
}
int main()
{
Complex<int> c(1, 2); //类模板是一定要显式调用的
//c.print();
cout << c << endl;
return 0;
}
#include <iostream>
using namespace std;
template <typename T>
class A //模板类
{
private:
T m_a;
public:
A(T a);
//void print();
};
template <typename T>
A<T>::A(T a)
{
m_a = a;
}
class B : public A<int> //模板类派生普通类
{
private:
int m_b;
public:
B(int b);
};
B::B(int b) : A<int>(1) //一定要显式调用
{
m_b = b;
}
template <typename T ,typename T2>
class C : public A<T2> //模板类派生模板类
{
private:
T m_c;
public:
C(T c, T2 a);
};
template <typename T ,typename T2>
C<T, T2>::C(T c, T2 a) : A<T2>(a) //也要显式调用
{
m_c = c;
}
int main()
{
B b(1);
C<int, double> c(1,2.57);
return 0;
}