STL类模板
笔记来源 : b站黑马程序员
语法
template<class T>
//template 声明创建模板
//typename 表明其后面的符号是一种数据类型,可以用class代替
//T 通用的数据类型,名称可以替换,通常为大写字母
template<class NameType, class AgeType>
class Person
{
public:
Person(NameType name, AgeType age)
{
this->m_Name = name;
this->m_Age = age;
}
void showPeron()
{
cout << "name: " << this->m_Name << endl
<< "age :" << this->m_Age << endl;
}
NameType m_Name;
AgeType m_Age;
};
void test()
{
Person<string, int> p1("jack", 99);
p1.showPeron();
}
与函数模板区别
1.类模板没有自动类型推导的使用方式
2.类模板在模板参数列表中可以有默认参数
//上一个案例中:
Person p1("jack", 99); // 这样是错的 , 因为类模板不能自动推导类型
Person<string, int> p1("jack", 99);//这样显式指定类型才可以
//但是可以像这样指定默认参数(只有类模板才可以这样用)
template<class NameType = string, class AgeType = int>
//这样在下面使用的时候就可以省略指定的类型了
成员函数创建时机
类模板中成员函数和普通类中成员函数创建时机是有区别的:
普通类中的成员函数一开始就可以创建
类模板中的成员函数在调用时才创建
类模板对象做函数参数
//1. 指定传入类型(实际开发中最常见)
//2. 参数模板化
//3. 整个类模板化
template<class T1, class T2>
class Person {
public:
Person(T1 name, T2 age) : m_Age(age), m_Name(name) {}
void showPerson() {
cout << this->m_Name << endl << this->m_Age << endl;
}
T1 m_Name;
T2 m_Age;
};
//1. 指定传入类型
void printPerson1(Person<string, int>&p) {
p.showPerson();
}
void test1() {
Person<string, int>p("111", 1000);
printPerson1(p);
}
//2. 参数模板化
template<class T1, class T2> //在这里告诉编译器有T1和T2两种类型
void printPerson2(Person<T1, T2>&p) {
p.showPerson();
//输出数据类型
cout << "T1 : " << typeid(T1).name() << endl;
cout << "T2 : " << typeid(T2).name() << endl;
}
void test2() {
Person<string, int>p("222", 1000);
printPerson2(p);
}
//3. 整个类模板化
template<class T>
void printPerson3(T& p) {
p.showPerson();
//输出数据类型
cout << "T : " << typeid(T).name() << endl;
}
void test3() {
Person<string, int>p("333", 1000);
printPerson3(p);
}
继承
- 当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中的类型如果不指定,编译器无法给子类分配内存
- 如果想灵活指定出父类中T的类型,子类也需变为类模板
template<class T>
class Base {
T m;
};
class Son : public Base<int> {};
//这里如果要继承,必须在Base里指定Base的T所代表的类型
//局限性 : 只能是一个指定的类型
template<class T>
class Base {
T m;
};
template<class T1, class T2>
//这里T1给了子类,在子类中使用, T2传给了父类
class Son : public Base<T2> {
public:
T1 m_X;
};
//子类使用模板就可以了
void test() {
Son<int, char> s;
//此时子类的是int, 父类的是char
}
成员函数类外实现
//构造函数类外实现
template<class T1,class T2>
Person<T1,T2>::Person(T1 name,T2 age)
{
this->m_Name = name;
this->m_Age = age;
}//模板参数列表始终在冒号的前面
template<class T1, class T2>
class Person {
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_Name;
T2 m_Age;
};
//构造函数的类外实现
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {
this->m_Age = age;
this->m_Name = name;
};
//成员函数的类外实现
template<class T1, class T2>
void Person<T1, T2>::showPerson() {
cout << this->m_Name << " " << this->m_Age << endl;
}
void test()
{
Person<string, int >p("123", 456);
p.showPerson();
}
分文件编写
问题:
类模板中成员函数创建时机是在调用阶段,致分文件编写时链接不到
解决:
解决方式1:直接在main里包含.cpp源文件而不是.h
解决方式2:将声明(.h)和实现(.cpp)写到同一个文件中,并更改后缀名为,hpp,hpp是约定的名称,并不强制
// Person.hpp
#include<string>
using namespace std;
template<class T1, class T2>
class Person {
public:
Person(T1 name, T2 age);
void show();
T1 m_Name;
T2 m_Age;
};
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {
this->m_Age = age;
this->m_Name = name;
}
template<class T1, class T2>
void Person<T1, T2>::show() {
cout << this->m_Name << " " << this->m_Age << endl;
}
// main.cpp
#include"Person.hpp"
void test() {
Person<string, int> p("13", 12);
p.show();
}
int main()
{
test();
return 0;
}
类模板和友元
全局函数类内实现·直接在类内声明友元即可
全局函数类外实现·需要提前让编译器知道全局函数的存在
//全局函数类内实现
template<class T1, class T2>
class Person {
public:
Person(T1 name, T2 age) : m_Name(name), m_Age(age) {}
friend void show(Person<T1, T2>p) {
cout << p.m_Name << " " << p.m_Age << endl;
};
private:
T1 m_Name;
T2 m_Age;
};
int main() {
Person<string, int>p("132", 20);
show(p);
return 0;
}
//全局函数类外实现
//提前让编译器知道有一个模板类Person存在
template<class T1, class T2>
class Person;
//提前让编译器知道模板类Person的全局友元函数存在
template<class T1, class T2>
void show(Person<T1, T2>p) {
cout << p.m_Name << " " << p.m_Age << endl;
}
template<class T1, class T2>
class Person {
public:
Person(T1 name, T2 age) : m_Name(name), m_Age(age) {}
friend void show<>(Person<T1, T2>p); //show后面加上<>表示空的模板参数列表
private:
T1 m_Name;
T2 m_Age;
};
int main() {
Person<string, int>p("132", 20);
show(p);
return 0;
}