01 类模板语法
#include<iostream>
using namespace std;
//类模板
template<class NameType,class AgeType>
class Person
{
public:
NameType m_Name;
AgeType m_Age;
public:
Person(NameType name, AgeType age)
{
this->m_Name = name;
this->m_Age = age;
}
void ShowPerson()
{
cout << "name:" << this->m_Name << " age:" << this->m_Age << endl;
}
};
void _01Test01()
{
Person<string, int> p("Tom", 18);//< >中就相当于模板形参列表
p.ShowPerson();
}
void main()
{
_01Test01();
}
02 类模板与函数模板的区别
//1、类模板没有自动类型推导的使用方式
//2、类模板在模板参数列表中可以有默认类型参数 函数模板不可以使用默认类型参数
#include<iostream>
using namespace std;
#include <string>
//类模板与函数模板的区别
//1、类模板没有自动类型推导的使用方式
//2、类模板在模板参数列表中可以有默认类型参数 函数模板不可以使用默认类型参数
template<class NameType, class AgeType=int>
class _02Person
{
public:
NameType m_Name;
AgeType m_Age;
public:
_02Person(NameType name, AgeType age)
{
this->m_Name = name;
this->m_Age = age;
}
void ShowPerson()
{
cout << "name:" << this->m_Name << " age:" << this->m_Age << endl;
}
};
//1、类模板没有自动类型推导的使用方式
void _02Test01()
{
//_02Person p("Tom", 19);//报错 类模板中没有自动类型推导
_02Person<string, int> p("Tom", 19);
p.ShowPerson();
}
//2、类模板在模板参数列表中可以有默认类型参数
void _02Test02()
{
//使类模板参数列表中的AgeType默认等于int
_02Person<string> p1("Tony", 20);
p1.ShowPerson();
_02Person<string, string>p2("Jack", "22");
p2.ShowPerson();
}
void main()
{
//_02Test01();
_02Test02();
}
03 类模板中成员函数的创建时机
//类模板中的成员函数并不是一开始就创建的 而是在模板调用时才创建
#include <iostream>
using namespace std;
//类模板中成员函数的创建时机
//类模板中的成员函数并不是一开始就创建的 而是在模板调用时才创建
class Person1
{
public:
void showPerson1()
{
cout << "调用showPerson1" << endl;
}
};
class Person2
{
public:
void showPerson2()
{
cout << "调用showPerson2" << endl;
}
};
template<class T>
class MyClass
{
public:
T obj;
public:
void func1()
{
obj.showPerson1();
}
void func2()
{
obj.showPerson2();
}
};
void _03Test01()
{
MyClass<Person1> myClass;
myClass.func1();
//myClass.func2();//编译报错 说明函数调用时才会去创建成员函数
}
void main()
{
_03Test01();
}
04 类模板对象做函数参数
//1、指定传入类型
//2、参数模板化
//3、整个类模板化 使用比较广泛
#include<iostream>
using namespace std;
#include<string>
//类模板对象做函数参数
template<class T1,class T2>
class _04Person
{
public:
T1 m_Name;
T2 m_Age;
_04Person(T1 name, T2 age)
{
this->m_Name = name;
this->m_Age = age;
}
void showPerson()
{
cout << "name:" << this->m_Name << " age:" << this->m_Age << endl;
}
};
//1、指定传入类型
void PrintPerson1(_04Person<string, int>& p)
{
p.showPerson();
}
void _04Test01()
{
_04Person<string, int> p("Tom", 19);
PrintPerson1(p);
}
//2、参数模板化
template<class T1,class T2>
void PrintPerson2(_04Person<T1, T2>& p)
{
cout << "T1类型:" << typeid(T1).name() << endl;
cout << " T2类型:" << typeid(T2).name() << endl;
p.showPerson();
}
void _04Test02()
{
_04Person<string, int> p("Tony", 29);
PrintPerson2(p);
}
//3、整个类模板化 使用比较广泛'
template<class T>
void PrintPerson3(T& p)
{
cout << "T的类型为:" << typeid(T).name() << endl;
p.showPerson();
}
void _04Test03()
{
_04Person<string, int> p("Jack", 39);
PrintPerson3(p);
}
void main()
{
_04Test01();
_04Test02();
_04Test03();
}
05 类模板与继承
//当类模板碰到继承时,需要注意以下几点:
//1、当子类继承的父类为类模板时,子类在声明时,必须指定父类中T的类型
//2、如果不指定,编译器无法给子类分配内存
//3、如果想灵活指定出父类中T的类型,子类也需要变为类模板
#include <iostream>
using namespace std;
//当类模板碰到继承时,需要注意以下几点:
//1、当子类继承的父类为类模板时,子类在声明时,必须指定父类中T的类型
//2、如果不指定,编译器无法给子类分配内存
//3、如果想灵活指定出父类中T的类型,子类也需要变为类模板
//类模板与继承
template<class T >
class Base
{
public:
T m_Member;
};
//如果不指定,编译器无法给子类分配内存
//class Son1:Base//报错 没有指明父类中T的数据类型
class Son1 :Base<int>
{
};
//如果想灵活指定出父类中T的类型,子类也需要变为类模板
template<class T1,class T2>
class Son2 :Base<T1>
{
public:
T2 m_Member2;
Son2()
{
cout << "T1的类型为:" << typeid(T1).name() << endl;
cout << "T2的类型为:" << typeid(T2).name() << endl;
}
};
void _05Test01()
{
Son2<char, int> s;
}
void main()
{
_05Test01();
}
06 类模板成员函数类外实现
#include<iostream>
using namespace std;
//类模板成员函数类外实现
template<class T1,class T2>
class Student
{
public:
T1 m_Name;
T2 m_Age;
Student(T1 name, T2 age);
void showStudent();
};
template<class T1,class T2>
Student<T1, T2>::Student(T1 name, T2 age)
{
this->m_Name = name;
this->m_Age = age;
}
template<class T1,class T2>
void Student<T1, T2>::showStudent()
{
cout << "姓名;" << this->m_Name << " 年龄:" << this->m_Age << endl;
}
void _06Test01()
{
Student<string, int >s1("Tom", 19);
s1.showStudent();
}
void main()
{
_06Test01();
}
07 类模板分文件编写
//类模板份文件编写问题和解决方法
//问题:
//类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
//解决方法:
//方式1:直接包含.cpp源文件
//方式2:将声名和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制
hpp文件:
#pragma once
#include<iostream>
using namespace std;
template<class T1, class T2>
class _07Person
{
public:
T1 m_Name;
T2 m_Age;
_07Person(T1 name, T2 age);
void showPerson();
};
template<class T1, class T2>
_07Person<T1, T2>::_07Person(T1 name, T2 age)
{
this->m_Name = name;
this->m_Age = age;
}
template<class T1, class T2>
void _07Person<T1, T2>::showPerson()
{
cout << "name:" << this->m_Name << " age:" << this->m_Age << endl;
}
#include<iostream>
using namespace std;
//类模板份文件编写问题和解决方法
//问题:
//类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
//解决方法:
//方式1:直接包含.cpp源文件
//#include"person.cpp"
//方式2:将声名和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制
#include"person.hpp"
void _07Test01()
{
_07Person<string, int> p("Tom", 18);
p.showPerson();
}
void main()
{
_07Test01();
}
08 类模板与友元
#include<iostream>
using namespace std;
//在编写友元函数实现之前还要提前声明类模板
template<class T1, class T2>
class _08Person;
//友元函数类外实现需要在类之前编写实现
template<class T1, class T2>
void showPerson2(_08Person<T1, T2> p)
{
cout << "name: " << p.m_Name << " age:" << p.m_Age << endl;
}
template<class T1, class T2>
class _08Person
{
//友元函数类内实现
friend void showPerson1(_08Person<T1, T2> p)
{
cout << "name: " << p.m_Name << " age:" << p.m_Age << endl;
}
//友元函数类外实现 还需要加空模板参数列表
//如果全局函数是类外实现,还需要让编译器提前知道这个函数的存在
friend void showPerson2<>(_08Person<T1, T2> p);
public:
T1 m_Name;
T2 m_Age;
_08Person(T1 name, T2 age)
{
this->m_Name = name;
this->m_Age = age;
}
};
void _08Test01()
{
_08Person<string, int>p("Jerry", 19);
showPerson1(p);
}
void _08Test02()
{
_08Person<string, int>p("Jack", 20);
showPerson2(p);
}
void main()
{
//_08Test01();
_08Test02();
}
09 类模板案例-通用数组类封装
MyArray.hpp文件:
//自己的通用的数组类
#pragma once
#include <iostream>
#include "MyArray.hpp"
using namespace std;
template<class T>
void PrintArray(MyArray<T>& arr)
{
for (int i = 0; i < arr.getSize(); i++)
{
cout << arr[i] << endl;
}
}
void _09Test01()
{
MyArray<int> arr1(5);
for (int i = 0; i < 5; i++)
{
arr1.Push_Back(i);
}
cout << "arr1的打印输出:" << endl;
PrintArray(arr1);
}
void _09Test02()
{
MyArray<string> arr(10);
arr.Push_Back("小一");
arr.Push_Back("小二");
arr.Push_Back("小三");
arr.Push_Back("小四");
arr.Push_Back("小五");
PrintArray(arr);
cout << "容量" << arr.getCapacity() << endl;
cout << "数量" << arr.getSize() << endl;
}
void main()
{
_09Test01();
_09Test02();
}
测试文件:
//自己的通用的数组类
#pragma once
#include <iostream>
#include "MyArray.hpp"
using namespace std;
template<class T>
void PrintArray(MyArray<T>& arr)
{
for (int i = 0; i < arr.getSize(); i++)
{
cout << arr[i] << endl;
}
}
void _09Test01()
{
MyArray<int> arr1(5);
for (int i = 0; i < 5; i++)
{
arr1.Push_Back(i);
}
cout << "arr1的打印输出:" << endl;
PrintArray(arr1);
}
void _09Test02()
{
MyArray<string> arr(10);
arr.Push_Back("小一");
arr.Push_Back("小二");
arr.Push_Back("小三");
arr.Push_Back("小四");
arr.Push_Back("小五");
PrintArray(arr);
cout << "容量" << arr.getCapacity() << endl;
cout << "数量" << arr.getSize() << endl;
}
void main()
{
_09Test01();
_09Test02();
}
补充:
类模板中的静态成员变量
不同的具体类所共享的静态成员变量不同
示例:
#include<iostream>
using namespace std;
//类模板中的静态成员变量
template<class T>
class MyClass10
{
public:
static int a;
};
//静态成员类外赋值
template<class T>
int MyClass10<T>::a = 0;
void main()
{
MyClass10<int> m1, m2,m3;
MyClass10<char> mm1, mm2, mm3;
m1.a = 10;
mm1.a = 100;
cout << "MyClass10<int>: m1:" << m1.a << " m2:" << m2.a << " m3:" << m3.a << endl;
cout << "MyClass10<char>: mm1:" << mm1.a << " mm2:" << mm2.a << " mm3:" << mm3.a << endl;
}