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;
}