page contents

C++——模板

C++——模板


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);

}


  • 发表于 2021-06-25 13:14
  • 阅读 ( 474 )
  • 分类:C/C++开发

0 条评论

请先 登录 后评论
小威
小威

64 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1312 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章