函数模板
-
模板的定义和模板的使用
#include "iostream" using namespace std; template <typename T> void myswap(T& a,T& b){ T swap; swap=a; a=b; b=swap; } int main(){ int a =10; int b=90; myswap(a,b); myswap<int>(a,b); cout<<a<<endl; }
-
函数模板只有是显式指定类型的时候才会发生自动类型转换(也建议使用模板的时候指定类型)
-
函数模板和普通函数的优先级后者更高,可以使用空模板参数来强制调用函数模板
-
函数模板可以产生重载
-
模板的具体化(使用重载)可以解决T为特殊类型的问题
template <class T> bool comp(T& a ,T& b ){ if(a==b){ return true; } else{ return false; } } template<> bool comp(Person& a ,Person& b){ if(a.age==b.age && a.height==b.height){ return true; } else{ return false; } }
类模板
- 类模板的定义
template<typename NameType ,typename AgeType>
class Person{
public:
Person(NameType name , AgeType age){
this->age=age;
this->name=name;
}
NameType name ;
AgeType age;
};
int main(){
Person<string,int>p1("kafen",21);
cout<<p1.name<<endl;
cout<<p1.age<<endl;
return 0;
}
- 类模板只能显式指定类型,类模板在参数列表中可以有默认参数,下面的不是自动类型推导,而是指定了类型
template<typename NameType=string ,typename AgeType=int >
class Person{
public:
Person(NameType name , AgeType age){
this->age=age;
this->name=name;
}
NameType name ;
AgeType age;
};
int main(){
Person<>p1("kafen",21);
cout<<p1.name<<endl;
cout<<p1.age<<endl;
return 0;
}
-
类模板中的成员函数的创建时机:在
调用的时候
才去创建 -
类模板对象作为函数参数,使用广泛的是指定类型,比如
void printPerson1(Person<string, int> &p)
-
类模板和继承:父类是一个类模板时,子类继承时需要指定父类中T的类型,如果想灵活指定,子类也需要变成一个类模板
template <typename T> class Base{ public: T t; }; class Son1: public Base<int>{//指定类型 public: string b ; }; template<typename T2> class Son2:public Base<T2>{//将子类变成类模板 // };
-
类模板成员函数类外实现
template <typename T> class Base{ public: T t; Base(T t); }; template <class T> Base<T>::Base(T t) { cout<<t<<endl; } int main(){ Base<int>(3); return 0; }
-
分文件编写的类模板:将声明和实现都写到
hpp
文件中 -
类模板和友元:建议全局函数类内实现
template <typename T> class Base{ friend void ShowArgs(Base<T> base){//全局函数类内实现 cout<<base.t<<endl; } private: T t; public: Base(T t){//构造函数 this->t=t; } }; int main(){ Base<int> b1(10); ShowArgs(b1); return 0; }
类模板的案例:实现一个数组类
标准模板库(STL)
- 容器:序列式容器,关联性数据
- 算法:质变算法(改元素)和非质变算法(不改元素)
- 迭代器:连接算法和容器,暂时可以先认为迭代器是一个指针
string容器
string
的构造没有可比性,我使用string s = “str”
string
的赋值使用=
就可- 字符串拼接相当于是拼接,使用
+=
就可 - 字符串查找
find()
,字符串替换replace(int,int,string*)
- 字符串比较
compare()
- 字符串插入
insert()
和删除erase()
- 获取子串
substr(int pos , int n)
Vector容器
- 遍历数组:可以只使用迭代器,也可以使用算法
#include "iostream"
#include "vector"
#include "algorithm"
using namespace std;
void func(int i ){
cout<<i<<endl;
}
int main(){
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
vector<int>::iterator pbegin =v.begin();
vector<int>::iterator pend =v.end();
while(pbegin!=pend){
cout<<*pbegin<<endl;
pbegin++;
}
for(vector<int>::iterator t=v.begin();t!=v.end();t++){
cout<<*t<<endl;
}
for_each(v.begin(),v.end(),func);
return 0;
}
- vector容器中放置自定义数据类型,也可以存放指针,只需要把
vector<int>::iterator
中的int
替换成对应的数据类型或者指针。 - 容器的嵌套(类似指针)
int main(){
vector<int> v01;
vector<int> v02;
vector<vector<int>> v0;
v01.push_back(1);
v01.push_back(2);
v01.push_back(3);
v02.push_back(10);
v02.push_back(20);
v02.push_back(30);
v0.push_back(v01);
v0.push_back(v02);
for(vector<vector<int>>::iterator it_outside = v0.begin();it_outside!=v0.end();it_outside++){
for(vector<int>::iterator it_inside=(*it_outside).begin();it_inside!=(*it_outside).end();it_inside++){
cout<<*it_inside<<endl;
}
}
}