C++类模板
一、类模板语法:
类模板和函数模板语法相似,在声明模板template后面加类,此称为类模板
template<class NameType,class AgeType> /
class Person
{
public:
Person(NameType name, AgeType age)
{
this->Name = name;
this->Age = age;
}
void showPerson()
{
cout << "Name = " << this->Name << " Age = " << this->Age << endl;
}
NameType Name;
AgeType Age;
};
void test01()
{
Person<string, int>p1("小明", 233);
p1.showPerson();
}
int main()
{
test01();
system("pause");
return 0;
}
二、类模板和函数模板区别:
1.类模板没有自动类型推导使用方式
2.类模板在模板参数列表中可以有默认参数
//类模板和函数模板区别
template<class NameType,class AgeType=int>
class Person
{
public:
Person(NameType name, AgeType age)
{
this->Name = name;
this->Age = age;
}
void showPerson()
{
cout << "Name = " << this->Name << " Age = " << this->Age << endl;
}
NameType Name;
AgeType Age;
};
//1.类模板没有自动类型推导使用方式
void test01()
{
//Person p("小明", 19); 错误,无法用自动类型推导
Person<string, int>p("小明", 19); //正确,只能用显示指定类型
p.showPerson();
}
//2.类模板在模板参数列表中可以有默认参数
void test02()
{
Person<string>p("小红", 22);
p.showPerson();
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
三、类模板对象做函数参数:
通过类模板创建的对象,可以有三种方式进行传参
比较广泛的是第一种:指定类型传入的类型
注意:要用到string类型要包含头文件
#include<string>
//类模板对象做函数参数
template<class T1,class T2>
class Person
{
public:
Person(T1 name, T2 age)
{
this->Name = name;
this->Age = age;
}
void showPerson()
{
cout << "姓名:" << this->Name << " 年龄:" << this->Age << endl;
}
T1 Name;
T2 Age;
};
1.指定传入类型
//1.指定传入类型
void printPerson1(Person<string, int>& p)
{
p.showPerson();
}
void test01()
{
Person<string, int>p("小明", 19);
printPerson1(p);
}
2.参数模板化
//2.参数模板化
template<class T1,class T2>
void printPerson2(Person<T1, T2>& p)
{
p.showPerson();
cout << "T1的类型为:" << typeid(T1).name() << endl; //显示T1的类型
cout << "T2的类型为:" << typeid(T2).name() << endl; //显示T2的类型
}
void test02()
{
Person<string, int>p("小红", 13);
printPerson2(p);
}
3.整个类模板化
//3.整个类模板化
template<class T>
void printPerson3(T& p)
{
p.showPerson();
cout << "T的数据类型为:" << typeid(T).name() << endl;
}
void test03()
{
Person<string, int>p("小猫", 3);
printPerson3(p);
}
四、类模板与继承:
//类模板与继承
template<typename T>
class Base
{
T m;
};
//class Son : public Base //错误,必须要知道父类中的T类型,才能继承给子类
class Son :public Base<int>
{
};
void test01()
{
Son s1;
}
//如果想灵活指定父类中T类型,子类也需要变类模板
template<class T1, typename T2>
class Son2 :public Base<T2>
{
public:
Son2()
{
cout << "T1的类型为:" << typeid(T1).name() << endl;
cout << "T2的类型为:" << typeid(T2).name() << endl;
}
T1 obj;
};
void test02()
{
Son2<int, char>S2;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
五、类模板成员函数类外实现:
//类模板成员函数类外实现
template<typename T,typename T1>
class Person
{
public:
Person(T name, T1 age);
void showPerson();
T Name;
T1 Age;
};
//构造函数类外实现
template<typename T,typename T1>
Person<T,T1>::Person(T name, T1 age)
{
this->Name = name;
this->Age = age;
}
//成员函数类外实现
template<typename T, typename T1>
void Person<T, T1>::showPerson()
{
cout << "姓名:" << this->Name << " 年龄:" << this->Age << endl;
}
void test01()
{
Person<string, int>p("小明", 12);
p.showPerson();
}
int main()
{
test01();
system("pause");
return 0;
}
六、类模板分文件编写:
第一种方法 直接包含源文件
person.h文件
#pragma once
#include<iostream>
using namespace std;
#include<string>
template<typename T,typename T1>
class Person
{
public:
Person(T name, T1 age);
void showPerson();
T Name;
T1 Age;
};
person.cpp文件
#include"person.h"
template<typename T, typename T1>
Person<T, T1>::Person(T name, T1 age)
{
this->Name = name;
this->Age = age;
}
template<typename T, typename T1>
void Person<T, T1>::showPerson()
{
cout << "姓名:" << this->Name << " 年龄:" << this->Age << endl;
}
main.cpp文件
#include"person.cpp"
void test01()
{
Person<string, int>P("小明", 15);
P.showPerson();
}
int main()
{
test01();
system("pause");
return 0;
}
第二种方法 将.h和.cpp中的内容写到一起,将后缀名改为.hpp文件
person.hpp文件
#pragma once
#include<iostream>
using namespace std;
#include<string>
template<typename T,typename T1>
class Person
{
public:
Person(T name, T1 age);
void showPerson();
T Name;
T1 Age;
};
template<typename T, typename T1>
Person<T, T1>::Person(T name, T1 age)
{
this->Name = name;
this->Age = age;
}
template<typename T, typename T1>
void Person<T, T1>::showPerson()
{
cout << "姓名:" << this->Name << " 年龄:" << this->Age << endl;
}
main.cpp文件
#include<iostream>
using namespace std;
#include "person.hpp"
void test01()
{
Person<string, int>P("小明", 15);
P.showPerson();
}
int main()
{
test01();
system("pause");
return 0;
}
七、类模板与友元
#include<iostream>
using namespace std;
#include<string>
//通过全局函数 打印Person信息
//提前让编译器知道Person类存在
template<typename T, typename T1>
class Person;
//类外实现
template<typename T, typename T1>
void printPerson2(Person<T,T1>p)
{
cout << " 类外实现 -------- 姓名:" << p.Name << " 年龄:" << p.Age << endl;
}
template<typename T,typename T1>
class Person
{
//全局函数 类内实现
friend void printPerson(Person<T, T1>p)
{
cout << "姓名:" << p.Name << " 年龄:" << p.Age << endl;
}
//全局函数 类外实现
//加空模板参数列表
//全局函数 是类外实现,需要让编译器提前知道这个函数的存在
friend void printPerson2<>(Person<T, T1>p);
public:
Person(T name, T1 age)
{
this->Name = name;
this->Age = age;
}
private:
T Name;
T1 Age;
};
//1.全局函数在类内实现
void test01()
{
Person<string, int>p("小明", 23);
printPerson(p);
}
//2.全局函数在类外实现
void test02()
{
Person<string, int>p("小红", 15);
printPerson2(p);
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
建议全局函数做类内实现,用法简单,而且编译器可以直接识别