C++
模板
模板是泛型编程的一个基础,模板就像练字本一样,你用钢笔,铅笔,圆珠笔都只需要照着练字本上面的那个字写,就可以写出来一个很漂亮的字。模板就如同这个一样,使我们能够最大限度的重用代码。
一、函数模板的基本用法
template<typename T> 这个是一个模板头,固定写法,下面紧跟一个类(类模板)或者函数(函数模板)
里面的任意类型可多写,template<typename T1,typename T2>,这样就是两个任意类型,T1,T2的命名要符合命名规则,typename可以以换成class,这里的效果是一样的
T:这里的是表示的一个任意类型,是一个类型
template<typename T>
void fun(T& a,T &b)
{cout<<a<<endl<<b<<endl;}
这里的fun函数的参数是一个任意类型的a和b
int a=1,b=2;char c='x';
fun(a,b);//隐式推导类型,需要有参数的类型才可以推导,相当于T是int类型
fun(a,c);//推导不出来T,因为的这里ac是不同的类型,而任意类型只有一个T,T不能即是int又是char
fun<int>(a,b);//显示指定类型,就是说我知道这个任意类型是什么类型,直接告诉了编译器
二、函数模板与普通函数的区别,以及调用原则
1、函数模板和普通函数可以重载
2、如果出现重载,优先调用普通函数,如果普通函数没有实现,报错
3、想要强制掉用模板,那么可以使用显示制定类型调用
4、如果函数模板可以产生更好的匹配,那么优先调用函数模板
三、模板的局限性及解决
template<class T>
bool myCompare(T &a, T &b)
{
if (a == b)
{
return true;
}
return false;
}
比如这个函数,如果说传的是个对象,那么不是能直接进行比较的,可以重载运算符==来进行一个比较,也可以使用语法:template<> 返回值 函数名<具体类型>(参数) {}
template<> bool myCompare<Person>(Person &a, Person &b)
{
if (a.m_Age == b.m_Age)
{
return true;
}
return false;
}
四、类模板的基本使用
template <class NameType, class AgeType = int> //类模板可以有默认类型
class Person
{
public:
Person(NameType name, AgeType age)
{
this->Name = name;
this->Age = age;
}
NameType Name;
AgeType Age;
};
使用:
Person p("王五",12);自动推到类型,类模板不支持
Person<string,int>("李四",13);必须使用显示指定类型
五、类模板做函数的参数
//类模板
template <class NameType, class AgeType = int> //类模板可以有默认类型
class Person
{
public:
Person(NameType name, AgeType age)
{
this->m_Name = name;
this->m_Age = age;
}
void showPerson()
{
cout << "姓名:" << this->m_Name << " 年龄: " << this->m_Age << endl;
}
NameType m_Name;
AgeType m_Age;
};
//1 、 指定传入类型
void doWork(Person<string, int> & p)//类的参数类型具体
{
p.showPerson();
}
void test01()
{
Person <string, int> p("MT", 10);
doWork(p);
}
//2、 参数模板化
template<class T1, class T2>
void doWork2(Person<T1, T2> & p)//类的参数类型模板化
{
//如何查看类型
cout << typeid(T1).name() << endl;//求T1的类型
cout << typeid(T2).name() << endl;//求T2的类型
p.showPerson();
}
void test02()
{
Person <string, int> p("李四", 18);
doWork2(p);
}
//3、 整体模板化
template<class T>
void doWork3(T&p)
{
cout << typeid(T).name() << endl;//求T的类型
p.showPerson();
}
void test03()
{
Person <string, int> p("张三", 18);
doWork3(p);
}
六、类模板和继承
template <class T>
class Base
{
public:
T m_A; //double类型
};
//child继承与 base必须告诉base中的T的类型,否则T无法分配内存
//在继承的是,子类继承的时候要知道父类的类型
class Child :public Base<int>
{
};
//child2 也是模板类
template<class T1, class T2>//两个任意类型,一个给父类用,一个自己用
class Child2 :public Base<T2>
{
public:
Child2()
{
cout << typeid(T1).name() << endl;
cout << typeid(T2).name() << endl;
}
public:
T1 m_B; //int类型
};
void test01()
{
Child2<int, double>child;//由用户指定类型
}
七、类模板类外实现成员函数
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> p1("Mt", 100);
p1.showPerson();
}
八、类模板的分文件编写
1、类模板中成员函数的创建是在调用阶段,导致份文件编写时链接不到,所以会报错
解决方法,直接讲声明和实现写到同一个头文件中,把后缀名改为.hpp,hpp是大佬们约定俗成的名称
九、类模板碰到了友元函数,类内实现
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", 10);
printPerson(p);
}
十、类模板碰到了友元函数,类外实现
//让编译器提前看到printPerson声明
//如果编译器看不到是会报错的,让编译器看到Person类声明,提前声明
template<class T1, class T2> class Person;
template<class T1, class T2>void printPerson(Person<T1, T2> & p);
template<class T1, class T2>
class Person
{
//友元函数类内实现 利用空参数列表 告诉编译器 模板函数的声明
friend void printPerson<>(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", 10);
printPerson(p);
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!