1. 类模板
类模板和函数模板的定义和使用类似,我们已经进行了介绍。有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同。
#include<iostream>
#include<string>
using namespace std;
//类模板和函数模板的定义和使用类似,我们已经进行了介绍。有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同。
//类模板用于实现类所需数据的类型参数化
template<class T1,class T2 = int>//类模板可以指定一个默认参数类型
class person
{
public:
person(T1 name,T2 age)
{
this->n_name =name;
this->n_age =age;
}
void printer()
{
cout<<"person.n_name:"<<this->n_name<<" "<<"person.n_age:"<<this->n_age<<endl;
}
private:
T1 n_name;
T2 n_age;
};
void main(){
//类型//person p;//类模板不能进行自动推导
person<string,int>p1("jojo",20);
p1.printer();
}
1.1 类内成员函数的创建时机
#include<iostream>
#include<string>
using namespace std;
class person1
{
public:
void showperson1()
{
cout<<"person1"<<endl;
}
};
class person2
{
void showperson2()
{
cout<<"person2"<<endl;
}
};
template<class T>
class typeend
{
public:
T obj;
//成员函数不会一开始就创建出来,而是在运行的时候创建
void show1()
{
obj.showperson1();
}
void show2()
{
obj.showperson2();
}
};
void main()
{
typeend<person1>p1;//不会报错,生成类的时候并没有直接生成成员函数
p1.show1();
//p1.show2();
}
成员函数不会一开始就创建出来,而是在运行的时候创建
1.3 类模板做函数参数
//类模板
template<class NameType, class AgeType>
class Person{
public:
Person(NameType name, AgeType age){
this->mName = name;
this->mAge = age;
}
void PrintPerson(){
cout << "Name:" << this->mName << " Age:" << this->mAge << endl;
}
public:
NameType mName;
AgeType mAge;
};
//类模板做函数参数
void DoBussiness(Person<string,int>& p){
p.mAge += 20;
p.mName += "_vip";
p.PrintPerson();
}
int main(){
Person<string, int> p("John", 30);
DoBussiness(p);
system("pause");
return EXIT_SUCCESS;
}
1.4类模板的派生类
#include<iostream>
#include<string>
using namespace std;
template<class nametaype,class agetype >
class person
{
public:
person(nametaype name,agetype age)
{
this->nname = name;
this->nage =age;
}
void showperson()
{
cout << "name: " << this->nname<< " age: " << this->nage<< endl;
}
private:
nametaype nname;
agetype nage;
};
//继承模板是必须告诉派生类T的类型,否则T无法分配内存
class teacher:public person<string,int>
{
public:
teacher(string name,int age):person(name,age){}
};
//派生类也是模板类
template<class T1,class T2,class T3>
class teacher1:public person<T2,T3>//用户指定类型
{
public:
teacher1(T1 a,T2 name,T3 age):person(name,age){}
T1 tmp;
void typeprint()
{
cout<<typeid(T1).name()<<endl;//输出a的类型
cout<<typeid(T2).name()<<endl;//输出name的类型
cout<<typeid(T3).name()<<endl;//输出age的类型
}
};
void main(){
teacher1<int,string,int>p1(10,"laowang",20);
p1.typeprint();
teacher p2("孙悟空",500);
p2.showperson();
}
1.5 类模板类内实现
#include<iostream>
#include<string>
using namespace std;
template<class NameType, class AgeType>
class Person
{
public:
Person(NameType name, AgeType age)
{
this->mName = name;
this->mAge = age;
}
void showPerson()
{
cout << "name: " << this->mName << " age: " << this->mAge << endl;
}
public:
NameType mName;
AgeType mAge;
};
void test01()
{
//Person P1("德玛西亚",18); // 类模板不能进行类型自动推导
Person<string, int>P1("德玛西亚", 18);
P1.showPerson();
}
void main()
{
test01();
}
1.6 类模板类外实现
#include<iostream>
#include<string>
using namespace std;
template<class T1, class T2>
class Person{
public:
Person(T1 name, T2 age);
void showPerson();
public:
T1 mName;
T2 mAge;
};
//类外实现
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age){
this->mName = name;
this->mAge = age;
}
template<class T1, class T2>
void Person<T1, T2>::showPerson(){
cout << "Name:" << this->mName << " Age:" << this->mAge << endl;
}
void test()
{
Person<string, int>p("Trume", 20);
p.showPerson();
}
int main(){
test();
system("pause");
return EXIT_SUCCESS;
}
2. 类模板的头文件书写
类模板的声明和实现放到一个文件中,我们把这个文件命名为.hpp
#pragma once
#include<iostream>
#include<string>
using namespace std;
template<class T1,class T2>
class Person{
public:
Person(T1 name,T2 age);
void ShowPerson();
public:
T1 mName;
T2 mAge;
};
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age){
this->mName = name;
this->mAge = age;
}
template<class T1, class T2>
void Person<T1, T2>::ShowPerson(){
cout << "Name:" << this->mName << " Age:" << this->mAge << endl;
}
头文件.hpp调用
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<string>
#include"Person.hpp"
//模板二次编译
//编译器编译源码 逐个编译单元编译的
int main(){
Person<string, int> p("Obama", 20);
p.ShowPerson();
system("pause");
return EXIT_SUCCESS;
}
类模板需要二次编译,在出现模板的地方编译一次,在调用模板的地方再次编译。
C++编译规则为独立编译。
1.9 模板类碰到友元函数
两种实现方式:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include <string>
//类外实现友元函数需要先声明类
template<class T1, class T2> class Person;
//告诉编译器这个函数模板是存在
template<class T1, class T2> void PrintPerson2(Person<T1, T2>& p);
//友元函数在类内实现
template<class T1, class T2>
class Person{
//1. 友元函数在类内实现
friend void PrintPerson(Person<T1, T2>& p){
cout << "Name:" << p.mName << " Age:" << p.mAge << endl;
}
//2.友元函数类外实现
//告诉编译器这个函数模板是存在
friend void PrintPerson2<>(Person<T1, T2>& p);
public:
Person(T1 name, T2 age){
this->mName = name;
this->mAge = age;
}
void showPerson(){
cout << "Name:" << this->mName << " Age:" << this->mAge << endl;
}
private:
T1 mName;
T2 mAge;
};
void test01()
{
Person <string, int>p("Jerry", 20);
PrintPerson(p);
}
// 类模板碰到友元函数
//友元函数类外实现 加上<>空参数列表,告诉编译去匹配函数模板
template<class T1 , class T2>
void PrintPerson2(Person<T1, T2>& p)
{
cout << "Name2:" << p.mName << " Age2:" << p.mAge << endl;
}
void test02()
{
Person <string, int>p("Tom", 20);
PrintPerson2(p);
}
int main(){
//test01();
test02();
return EXIT_SUCCESS;
}