目录
知识点1【函数模板的概述】(了解)
1、函数模板概述
2、函数模板 会自动推导 参数的类型
3、函数模板 可以显示指定T的类型
4、函数模板 和 普通函数同名
5、提供具体化的模板
知识点2【类模板】(了解)
1、类模板的定义
2、类模板的成员函数 在类外实现
3、类模板作为函数的参数
4、类模板 派生 普通类
5、类模板 派生 类模板
6、类模板 头文件和源文件 分离问题(.hpp)
知识点3【类模板和友元】(了解)
1、普通函数 作为 类模板 的友元
2、函数模板 作为 类模板的友元
知识点4【设计数组类模板】(了解)
知识点1【函数模板的概述】(了解)
模板的分类:函数模板、类模板。
函数返回值类型和形参类型不具体制定,用一个虚拟的类型来代表。这个通用函数就成为函数模板。
模板的关键字:template
template<typename T>
void swapAll(T & a,T & b)
{
T temp = a;
a = b;
b = temp;
}
int a = 10, b = 20;
swapAll(a, b);---->int替換T 进行二次编译
函数模板、类模板:(进行两次编译)
第一次编译:不在乎T具体是啥类型 对函数模板本身进行编译
第二次编译:在函数模板 调用处 分析T的类型,进行二次编译
1、函数模板概述
template<typename T>
void swapAll(T & a,T & b)
{
T temp = a;
a = b;
b = temp;
}
void test01()
{
int a = 10, b=20;
cout<<"a="<<a<<", b="<<b<<endl;
swapAll(a, b);
cout<<"a="<<a<<", b="<<b<<endl;
char a1 = 'A', b1='B';
cout<<"a1="<<a1<<", b1="<<b1<<endl;
swapAll(a1, b1);
cout<<"a1="<<a1<<", b1="<<b1<<endl;
}
//a=10, b=20
//a=20, b=10
//a1=A, b1=B
//a1=B, b1=A
2、函数模板 会自动推导 参数的类型
3、函数模板 可以显示指定T的类型
template<typename T>
T myAdd(T a, T b)
{
return a+b;
}
void test02()
{
int a=10;
char b = 'B';
// 无法自动推导 a b类型不一致
//cout<<myAdd(a,b)<<endl;
//显示指定T的类型
cout<<myAdd<int>(a,b)<<endl;
}
4、函数模板 和 普通函数同名
//函数模板
template<typename T>
T myAdd(T a, T b)
{
cout<<"函数模板"<<endl;
return a+b;
}
//普通函数
int myAdd(int a, int b)
{
cout<<"普通函数"<<endl;
return a+b;
}
void test02()
{
int a = 10, b = 20;
//函数模板和普通函数 都识别 优先选择 普通函数
cout<<myAdd(a,b)<<endl;
//函数模板和普通函数 都识别 强制调用函数模板
cout<<myAdd<>(a,b)<<endl;
}
写两个函数模板联系一下吧:
1、写一个可以遍历任何类型数组(将数组内容通过标准输出打印出来)
2、写一个可以排序任何类型数组(从大到小的顺序排序)
#include <iostream>
#include <cstring>
using namespace std;
template <class T>
void printArray(T arr[], int len){
for(int i=0; i<len; i++){
cout<<arr[i]<<"";
}
cout<<endl;
}
template <class T>
void mysort(T arr[], int len){
for(int i=0; i<len; i++){
for(int j=len-1; j>i; j--){
if(arr[j] > arr[j-1]){
T temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
}
}
}
}
int main(int argv, char **argc){
char tempchar[] = "helloworld";
int charlen = strlen(tempchar);
int tempInt[] = {7, 4, 2, 9, 8, 1};
int intlen = sizeof(tempInt)/sizeof(tempInt[0]);
printArray(tempchar, charlen);
printArray(tempInt, intlen);
mysort(tempchar, charlen);
mysort(tempInt, intlen);
printArray(tempchar, charlen);
printArray(tempInt, intlen);
return 0;
}
/*
helloworld
742981
wroolllhed
987421
*/
5、提供具体化的模板
#include<string>
class Person
{
public:
int num;
string name;
public:
Person(){}
Person(int num, string name)
{
this->num = num;
this->name = name;
}
};
template<typename T>
T getMaxData(T a, T b)
{
return a>b?a:b;//err 当a b是自定义对象 无法执行>运算符
//解决办法一:重载>运算
}
void test04()
{
cout<<getMaxData(10,20)<<endl;
cout<<getMaxData('A','B')<<endl;
Person ob1(100,"lucy");
Person ob2(100,"bob");
Person ret = getMaxData(ob1, ob2);
cout<<ret.num<<", "<<ret.name<<endl;
}
函数模板的具体化:
#include<string>
class Person
{
public:
int num;
string name;
public:
Person(){}
Person(int num, string name)
{
this->num = num;
this->name = name;
}
#if 1
bool operator>(Person ob)
{
cout<<"运算符重载"<<endl;
if(num > ob.num)
return true;
return false;
}
#endif
};
template<typename T>
T getMaxData(T a, T b)
{
return a>b?a:b;//err 当a b是自定义对象 无法执行>运算符
//解决办法一:重载>运算
//解决办法一:重载>运算
}
//模板的具体化
template<> Person getMaxData<Person>(Person a, Person b)
{
cout<<"具体化"<<endl;
if(a.num > b.num)
return a;
return b;
}
void test04()
{
cout<<getMaxData(10,20)<<endl;
cout<<getMaxData('A','B')<<endl;
Person ob1(100,"lucy");
Person ob2(200,"bob");
Person ret = getMaxData(ob1, ob2);
cout<<ret.num<<", "<<ret.name<<endl;
}
int main(int argc, char *argv[])
{
test04();
return 0;
}

知识点2【类模板】(了解)
1、类模板的定义
函数模板 的T 可以自动类型推导
类模板 的T 不可以自动类型推导 必须人为指定。
template<class T>
class Data
{
public:
T a;
T b;
public:
Data(T a, T b)
{
this->a = a;
this->b = b;
}
void showData()
{
cout<<"a="<<a<<", b="<<b<<endl;
}
};
void test05()
{
//类模板 必须显示指定T的类型
//Data ob(10,20);//err
Data<int> ob1(10,20);
Data<char> ob2('A','B');
ob1.showData();
ob2.showData();
}
2、类模板的成员函数 在类外实现
template<class T>
class Data
{
public:
T a;
T b;
public:
Data(T a, T b);
void showData();
};
template<class T>
Data<T>::Data(T a, T b)
{
this->a = a;
this->b = b;
}
template<class T>
void Data<T>::showData()
{
cout<<"a="<<a<<", b="<<b<<endl;
}
void test05()
{
//类模板 必须显示指定T的类型
//Data ob(10,20);//err
Data<int> ob1(10,20);
Data<char> ob2('A','B');
ob1.showData();
ob2.showData();
}
3、类模板作为函数的参数
template<class T>
class Data
{
public:
T a;
T b;
public:
Data(T a, T b);
void showData();
};
template<class T>
Data<T>::Data(T a, T b)
{
this->a = a;
this->b = b;
}
template<class T>
void Data<T>::showData()
{
cout<<"a="<<a<<", b="<<b<<endl;
}
//void printData(const Data<int> &ob)
void printData(Data<int> ob)
{
cout<<"a="<<ob.a<<", b="<<ob.b<<endl;
}
void test05()
{
Data<int> ob(10, 20);
printData(ob);
}
4、类模板 派生 普通类
????????基类:类模板
????????子类:普通类
#include <iostream>
using namespace std;
//类模板
template<class T>
class Base
{
public:
T a;
public:
Base(){cout<<"Base无参构造"<<endl;}
Base(T a)
{
cout<<"有参构造"<<endl;
this->a = a;
}
~Base()
{
cout<<"Base的析构函数"<<endl;
}
};
//普通类
class Son:public Base<int>//继承类模板的时候,必须要确定基类的大小
{
public:
int b;
public:
Son()
{
cout<<"Son的无参构造"<<endl;
}
Son(int a, int b):Base<int>(a),b(b)
{
cout<<"Son的有参构造"<<endl;
}
~Son()
{
cout<<"Son析构函数"<<endl;
}
};
int main(int argc, char *argv[])
{
Son ob(10, 20);
cout<<"ob.a="<<ob.a<<", ob.b="<<ob.b<<endl;
return 0;
}

5、类模板 派生 类模板
????????基类:类模板
????????子类:类模板
#include <iostream>
using namespace std;
//类模板
template<class T>
class Base
{
public:
T a;
public:
Base(){cout<<"Base无参构造"<<endl;}
Base(T a)
{
cout<<"有参构造"<<endl;
this->a = a;
}
~Base()
{
cout<<"Base的析构函数"<<endl;
}
};
//类模板
template<class T1, class T2>
class Son:public Base<T1>
{
public:
T2 b;
public:
Son()
{
cout<<"Son的无参构造"<<endl;
}
Son(T1 a, T2 b):Base<T1>(a),b(b)
{
cout<<"Son的有参构造"<<endl;
}
~Son()
{
cout<<"Son析构函数"<<endl;
}
};
int main(int argc, char *argv[])
{
Son<int, char> ob(10, 'B');
cout<<"ob.a="<<ob.a<<", ob.b="<<ob.b<<endl;
return 0;
}

6、类模板 头文件和源文件 分离问题(.hpp)
????????建议不分离
????????类模板定义和类模板成员函数实现都在.hpp文件中
????????data.hpp
#ifndef DATA_H
#define DATA_H
#include<iostream>
using namespace std;
template<class T>
class Data
{
public:
T a;
public:
Data();
Data(T a);
void setA(T a);
T getA(void);
};
template<class T>
Data<T>::Data()
{
cout<<"无参构造"<<endl;
}
template<class T>
Data<T>::Data(T a)
{
this->a = a;
cout<<"有参构造"<<endl;
}
template<class T>
void Data<T>::setA(T a)
{
this->a = a;
return;
}
template<class T>
T Data<T>::getA()
{
return a;
}
#endif // DATA_H
????????main.cpp
#include <iostream>
#include "data.hpp"
using namespace std;
int main(int argc, char *argv[])
{
Data<int> ob;
ob.setA(100);
cout<<ob.getA()<<endl;
return 0;
}

知识点3【类模板和友元】(了解)
1、普通函数 作为 类模板 的友元
//普通函数作为类模板的友元
void printData01(Data<int> ob)
{
cout<<"a="<<ob.a<<endl;
}
template <class T>
class Data{
friend void printdata01(Data<int> ob);
private:
T a;
public:
Data(){
cout << "无参构造" << endl;
}
};
2、函数模板 作为 类模板的友元
//函数模板 作为 类模板的友元
template<typename T2>
void printData02(Data<T2> ob)
{
cout<<"a="<<ob.a<<endl;
}
template <class T>
class Data{
friend void printdata01(Data<int> ob);
template<typename T2> friend void printData01(Data<T2> ob);
private:
T a;
public:
Data(){
cout << "无参构造" << endl;
}
};
#include <iostream>
using namespace std;
template<class T>
class Data
{
friend void printData01(Data<int> ob);
template<typename T2>friend void printData02(Data<T2> ob);
private:
T a;
public:
Data()
{
cout<<"无参构造"<<endl;
}
Data(T a)
{
this->a = a;
cout<<"有参构造"<<endl;
}
};
//普通函数作为类模板的友元
void printData01(Data<int> ob)
{
cout<<"a="<<ob.a<<endl;
}
//函数模板 作为 类模板的友元
template<typename T2>
void printData02(Data<T2> ob)
{
cout<<"a="<<ob.a<<endl;
}
int main(int argc, char *argv[])
{
Data<int> ob(100);
printData01(ob);
Data<char> ob2('B');
printData02(ob2);
return 0;
}

知识点4【设计数组类模板】(了解)
myarray.hpp
#ifndef MYARRAY_HPP
#define MYARRAY_HPP
#include<iostream>
#include<cstring>
using namespace std;
template<class T>
class MyArray
{
private:
T *addr;
int capacity;
int size;
public:
MyArray()
{
capacity=5;
size = 0;
addr = new T[capacity];
memset(addr, 0, capacity*sizeof(T));
cout<<"无参构造"<<endl;
}
MyArray(int capacity)
{
this->capacity = capacity;
size = 0;
addr = new T[capacity];
memset(addr, 0, capacity*sizeof(T));
cout<<"有参构造"<<endl;
}
MyArray(const MyArray &ob)
{
capacity = ob.capacity;
size = ob.size;
addr = new T[capacity];
memcpy(addr, ob.addr, sizeof(T)*capacity);
cout<<"拷贝构造函数"<<endl;
}
~MyArray()
{
cout<<"析构函数"<<endl;
if(addr != NULL )
{
delete [] addr;
addr=NULL;
}
}
int getSize(void)
{
return size;
}
int getCapacity(void)
{
return capacity;
}
//往数组尾部插入
void push_back(T value)
{
//判断数组是否满
if(size == capacity)
{
cout<<"数组已满,无法插入"<<endl;
return;
}
else
{
addr[size] = value;
size++;
}
return;
}
//尾部删除
void pop_back(void)
{
if(size == 0)
{
cout<<"数组为空,无法删除"<<endl;
return;
}
else
{
addr[size-1]=0;
size--;
}
return;
}
//重载[]运算符
T& operator[](int pos)
{
if(pos>=0 && pos<size)
{
return addr[pos];
}
else
{
cout<<"数组下标非法"<<endl;
}
}
};
#endif // MYARRAY_HPP
main.cpp
#include <iostream>
#include "myarray.hpp"
#include<string>
using namespace std;
class Hero
{
friend ostream& operator<<(ostream &out, Hero ob);
private:
string name;
int def;
int atk;
public:
Hero(){}
Hero(string name, int def, int atk)
{
this->name = name;
this->def = def;
this->atk = atk;
}
};
ostream& operator<<(ostream &out, Hero ob)
{
out<<ob.name<<" "<<ob.def<<" "<<ob.atk<<endl;
return out;
}
int main(int argc, char *argv[])
{
MyArray<int> arr1;
arr1.push_back(10);
arr1.push_back(20);
arr1.push_back(30);
arr1.push_back(40);
int i=0;
for(i=0;i<arr1.getSize(); i++)
{
cout<<arr1[i]<<" ";
}
cout<<endl;
arr1[2]=3000;
for(i=0;i<arr1.getSize(); i++)
{
cout<<arr1[i]<<" ";
}
cout<<endl;
MyArray<char> arr2;
arr2.push_back('A');
arr2.push_back('B');
arr2.push_back('C');
arr2.push_back('D');
for(i=0;i<arr2.getSize(); i++)
{
cout<<arr2[i]<<" ";
}
cout<<endl;
MyArray<Hero> arr3;
arr3.push_back(Hero("德玛西亚", 70, 100));
arr3.push_back(Hero("小炮", 90, 80));
arr3.push_back(Hero("艾希", 60, 70));
arr3.push_back(Hero("小法", 70, 100));
for(i=0;i<arr3.getSize(); i++)
{
cout<<arr3[i]<<" ";
}
cout<<endl;
return 0;
}

|