模板
目录
概念
模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码,即不具体制定数据类型
模板是创建泛型类或函数的蓝图或公式
函数模板
基本语法
#include <iostream>
#include <cstdio>
using namespace std;
// 函数模板实现通用数据类型交换
template<typename T> // T属于通用数据类型
void mySwap(T &a,T &b) { // 模板可以将类型参数化
T temp = a;
a = b;
b = temp;
}
// 使用函数模板
void test01() {
// 1. 自动类型推导
int a = 0,b = 1;
cout << "a = " << a << ",b = " << b << endl;
mySwap(a,b);
cout << "a = " << a << ",b = " << b << endl;
// 2. 显式指定类型
mySwap<int>(a,b);
cout << "a = " << a << ",b = " << b << endl;
mySwap(a,b);
cout << "a = " << a << ",b = " << b << endl;
// 注意:模板必须推导出T的类型才能使用,否则不能单独使用
}
int main() {
test01();
return EXIT_SUCCESS;
}
a = 0,b = 1
a = 1,b = 0
a = 0,b = 1
a = 1,b = 0
函数模板与普通函数区别
- 普通函数可以发生隐式类型转化
- 如果普通函数和函数模板(同名)都可以匹配,优先匹配普通函数
- 如果要强制调用函数模板,则要加空模板参数列表
mySwap<>(a,b)
- 函数模板也可以产生函数重载
- 如果函数模板可以产生更好的匹配,那么优先匹配函数模板
函数模板的局限和解决
#include <iostream>
using namespace std;
class Person
{
public:
int m_Age;
Person(int age) : m_Age(age) {
;
}
};
// 模板并不真正通用
// 对于特殊数据类型,可以具体化实现
template<class T>
bool myCompare(T &a, T &b) {
return a == b;
}
// 利用具体化实现,解决特殊数据类型
// 语法:template<> 函数名 + 具体实现
template<> bool myCompare(Person &a, Person &b) {
return a.m_Age == b.m_Age;
}
int main() {
Person p1 = Person(18);
Person p2 = Person(20);
cout << myCompare(p1,p2) << endl;
return EXIT_SUCCESS;
}
0
类模板
基本语法
#include <iostream>
#include <string>
using namespace std;
// 模板中也可以指定默认参数
template<class T1,class T2 = int>
class Person
{
public:
T1 m_Name;
T2 m_Age;
Person(T1 name, T2 age) {
this->m_Age = age;
this->m_Name = name;
}
};
int main() {
// Person p(18,"Tom"); 类模板使用时,不可以自动类型推导,必须显式指定
Person <string,int>p("Tom",18);
return EXIT_SUCCESS;
}
类模板中成员函数创建时机
#include<iostream>
using namespace std;
class Person1
{
public:
void showPerson1()
{
cout << "showPerson1" << endl;
}
};
class Person2
{
public:
void showPerson2()
{
cout << "showPerson2" << endl;
}
};
//类模板中成员函数并不是一开始创建,而是在替换T后,才去生成
template<class T>
class testClass
{
public:
void func1()
{
obj.showPerson1();
}
void func2()
{
obj.showPerson2();
}
T obj;
};
void test01()
{
testClass<Person2>tc;
//tc.func1();
tc.func2();
}
int main(){
test01();
return EXIT_SUCCESS;
}
类模板做函数参数
#include<iostream>
using namespace std;
#include <string>
//模板中 也可以使用默认参数
template<class T1, class T2>
class Person
{
public:
Person(T1 name, T2 age)
{
this->m_Name = name;
this->m_Age = age;
}
void showPerson()
{
cout << "姓名: " << this->m_Name << " 年龄: " << this->m_Age << endl;
}
T1 m_Name;
T2 m_Age;
};
//1、指定传入类型
void doWork(Person <string, int>&p)
{
p.showPerson();
}
void test01()
{
Person <string,int>p1("Tom", 100);
doWork(p1);
}
//2、将参数模板化
template<class T1,class T2>
void doWork2(Person <T1, T2>&p)
{
cout << "T1 = " << typeid(T1).name() << endl;
cout << "T2 = " << typeid(T2).name() << endl;
p.showPerson();
}
void test02()
{
Person <string, int>p1("Jerry", 100);
doWork2(p1);
}
//3、将类模板化
template<class T>
void doWork3(T &p)
{
cout << "T = " << typeid(T).name() << endl;
p.showPerson();
}
void test03()
{
Person <string, int>p1("Bill", 100);
doWork3(p1);
}
int main(){
//test01();
//test02();
test03();
system("pause");
return EXIT_SUCCESS;
}
T = 6PersonINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiE
姓名: Bill 年龄: 100
类模板遇到继承时的问题和解决
#include<iostream>
using namespace std;
template<class T>
class Base
{
public:
T m_A;
};
//子类在继承时,必须确定出父类的T的数据类型,否则无法给T分配内存空间
class Son :public Base<int>
{
};
template<class T>
class Base2
{
public:
T m_A;
};
template<class T1, class T2>
class Son2 :public Base2<T2>
{
public:
Son2()
{
cout << "T1的类型为: " << typeid(T1).name() << endl;
cout << "T2的类型为: " << typeid(T2).name() << endl;
}
T1 m_B;
};
void test01()
{
Son2<int, double> s;
}
int main(){
test01();
system("pause");
return EXIT_SUCCESS;
}
T1的类型为: i
T2的类型为: d
类模板成员函数类外实现
#include<iostream>
using namespace std;
#include <string>
template<class T1, class T2>
class Person
{
public:
Person(T1 name, T2 age);
//{
// this->m_Name = name;
// this->m_Age = age;
//}
void showPerson();
//{
// cout << "姓名: " << this->m_Name << " 年龄: " << this->m_Age << endl;
//}
T1 m_Name;
T2 m_Age;
};
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>
void Person<T1,T2>::showPerson()
{
cout << "姓名: " << this->m_Name << " 年龄: " << this->m_Age << endl;
}
void test01()
{
Person<string, int>p("aaa", 10);
p.showPerson();
}
int main(){
test01();
return EXIT_SUCCESS;
}
姓名: aaa 年龄: 10
类模板和友元
类内实现
#include<iostream>
using namespace std;
#include <string>
template<class T1,class T2>
class Person
{
friend void printPerson(Person<T1, T2>& p)
{
cout << "姓名: " << p.m_Name << " 年龄: " << p.m_Age << endl;
}
public:
Person(T1 name, T2 age)
{
this->m_Name = name;
this->m_Age = age;
}
private:
T1 m_Name;
T2 m_Age;
};
void test01()
{
Person<string, int>p("Tom", 111);
printPerson(p);
}
int main(){
test01();
return EXIT_SUCCESS;
}
类外实现
#include<iostream>
using namespace std;
#include <string>
//先让编译器看到Person类声明
template<class T1, class T2>class Person;
//先让编译器看到函数模板 printPerson的存在
template<class T1, class T2> void printPerson(Person<T1, T2>& p);
template<class T1, class T2>
void printPerson2(Person<T1, T2>& p)
{
cout << "姓名: " << p.m_Name << " 年龄: " << p.m_Age << endl;
}
template<class T1, class T2>
class Person
{
friend void printPerson<>(Person<T1, T2>& p);
friend void printPerson2<>(Person<T1, T2>& p);
public:
Person(T1 name, T2 age)
{
this->m_Name = name;
this->m_Age = age;
}
private:
T1 m_Name;
T2 m_Age;
};
template<class T1,class T2>
void printPerson(Person<T1, T2>& p)
{
cout << "姓名: " << p.m_Name << " 年龄: " << p.m_Age << endl;
}
void test01()
{
Person<string, int>p("Tom", 222);
printPerson(p);
printPerson2(p);
}
int main(){
test01();
return EXIT_SUCCESS;
}