1、类模板实现
函数模板在调用时可以自动类型推导
类模板必须显式指定类型
#include<iostream>
using namespace std;template<class T>
class Person {
public:T mId;T mAge;
public:Person(T id,T age){this->mAge = age;this->mId = id;}void Show(){cout << "ID:" << mId << " Age:" << mAge << endl;}
};void test01()
{//函数模板在调用时可以自动类型推导//类模板必须显式指定类型Person<int> p(10, 20);p.Show();
}int main(void)
{test01();return 0;
}
2、类模板派生普通类
注意:
(1)class Cat :public Animal<int> //继承时必须指定类型
(2)Cat(int age,int id ,int color):Animal<int>(age,id) //构造函数也需要继承
#include<iostream>using namespace std;
template<class T>
class Animal
{
public:T mAge;T mId;public:Animal(T age, T id){this->mAge = age;this->mId = id;}void Show(){cout << "父类" << endl;cout << "ID:" << mId << " Age:" << mAge << endl;}
};
class Cat :public Animal<int> //继承时必须指定类型
{
public:int mColor;
public:Cat(int age,int id ,int color):Animal<int>(age,id){mAge = age;mId = id;this->mColor = color;}void Show(){cout << "子类" << endl;cout << "ID:" << mId << " Age:" << mAge<< " mColor:"<<mColor<< endl;}};int main(void)
{Animal<int> a(12,12);a.Show();Cat c(1,1,1);c.Show();return 0;
}
运行结果:
3、类模板派生类模板
注意:
(1)template<class T> class B:public A<T> //继承时不需要指定类型
(2)B(T age,T id ,T color):A<T>(age,id) //虽然不需要具体指定类型但是构造函数也需要继承
#include<iostream>using namespace std;
template<class T>
class A
{
public:T mAge;T mId;public:A(T age, T id){this->mAge = age;this->mId = id;}void Show(){cout << "父类" << endl;cout << "ID:" << mId << " Age:" << mAge << endl;}
};
template<class T>
class B :public A<T> //继承时必须指定类型
{
public:int mColor;
public:B(T age,T id ,T color):A<T>(age,id){mAge = age;mId = id;this->mColor = color;}void Show(){cout << "子类" << endl;cout << "ID:" << mId << " Age:" << mAge<< " mColor:"<<mColor<< endl;}};int main(void)
{A<int> a(12,12);a.Show();B<double> c(1.21,1.22,1.23);c.Show();return 0;
}
运行结果:
4、类模板类外实现
注意类模板中友缘函数的使用
#include<iostream>
using namespace std;//不要滥用友缘函数//类外声明 普通友缘函数方法二
template<class T> class Person;
template<class T> void PrintPerson(Person<T>& p);template<class T>
class Person {
public://重载左移操作符 此方法linux可能编译不通过template<class T>friend ostream& operator<<(ostream& os, Person<T>& p);//friend ostream& operator<<<T>(ostream& os, Person<T>& p);//普通友缘函数方法一 需要添加template<class T>/*template<class T>friend void PrintPerson(Person<T>& p);*///普通友缘函数方法二 friend void PrintPerson<T>(Person<T>& p);Person(T age, T id);void show();
private:T mAge;T mID;
};template<class T>
Person<T>::Person(T age, T id)
{this->mID = id;this->mAge = age;
}
template<class T>
void PrintPerson(Person<T>& p)
{cout << "Age:" << p.mAge << " ID:" << p.mID << endl;
}
template<class T>
void Person<T>::show()
{cout << "Age:" << mAge << " ID:" << mID << endl;
}//重载左移运算操作符
template<class T>
ostream& operator<<(ostream &os, Person<T>& p)
{os << "Age:" << p.mAge << " ID:" << p.mID << endl;return os;
}void test01()
{Person<int> p(10, 20);p.show();PrintPerson(p);cout << p;
}int main(void)
{test01();return 0;
}
5、类模板.h和.cpp分离编写
注意:
(1)一般在写类模板时将Person.h和Person.cpp合并一起写。写为Person.hpp(hpp即h和cpp的合并).否则可能会报错
(2)当分开写时,main.cpp 中include的是Person.cpp。因为只有这样在编译Person<int> p(10)时,编译器才会找到构造函数并生成具体函数使用。当include的时Person.h时,编译main.cpp时,在运行到Person<int> p(10)时,以为会在其他处有声明,然而只有有Person<T>::Person(T age)的声明,而没有具体类型构造函数的声明。(模板函数的二次编译:一次声明编译,一次具体调用编译)
如:
Person.h
#pragma once#include <iostream>
using namespace std;//声明是不编译的
template<class T>
class Person {
public:Person(T age);void Show();
public:T mAge;
};
Person.cpp
#include"Person.h"
//函数模板是二次编译
//定义时一次编译,并没有生成具体的函数
//具体调用第二次编译
template<class T>
Person<T>::Person(T age)
{this->mAge = age;
}template<class T>
void Person<T>::Show()
{cout << "Age:" << mAge << endl;
}
main.cpp
#include<iostream>
//#include"Person.h" 错误
#include"Person.cpp"//正确,
//因为Person<int> p(10)在编译时用到Person<T>::Person(T age)生成具体的使用函数
//所以在写类模板时一般写为Person.hpp 意味着h和cpp的合体
int main(void)
{//让链接器找文件//C++独立编译。第一次编译时,构造函数定义在当前文件没有找到//因为此函数有声明,编译器认为这个函数在其他文件中定义//让链接器在链接时 去找这个函数的具体位置,如何实现//然而链接器在链接时,发现并没有此函数的定义,因为次函数的编译是函数模板的第一次编译,找不着//报错Person<int> p(10);p.Show();return 0;
}
运行结果:
6、类模板中static关键字的使用
#include<iostream>
using namespace std;template<class T>
class Person {
public:static int a;
};
//类外初始化
template<class T> int Person<T>::a = 0;
int main(void)
{Person<int> p1, p2, p3;Person<char> pb1, pb2, pb3;p1.a = 10;pb1.a = 100;cout << "p.a:" << p1.a <<" "<<p2.a << " " <<p3.a<< endl;cout << "pb.a:" << pb1.a << " " <<pb2.a << " " <<pb3.a<< endl;return 0;
}