作用:

减少程序中的冗余信息。如:多个函数或类的除了参数类型外,其余都完全相同时,可以使用模板来减少重复信息(参考函数重载时,输入参数数量也相同的情况)

1、函数模板

即建立一个通用函数,只不过该函数的返回类型和形参类型都不具体指定,其定义格式如下:

template <typename 类型名>

类型名或void  函数名(类型名 形参表)

{

函数体

}

template <class 类型名>

类型名或void  函数名(类型名 形参表)

{

函数体

}

1、此处的类型名是由开发人员自己决定的。

2、一般不注重向后兼容且愿意输入较长的类型名时,选用typename。

代码示例:

#include <iostream>
#include <string>
using namespace std;template <typename ty_na>
ty_na func_name(ty_na* parameters, int size = 0) {ty_na first_num = parameters[size];return first_num;
}int main()
{int array_int[] = {1,2,3,4,5};int first_num = func_name(array_int, 0);cout << first_num << endl;return 0;
}

此外,由于函数模板也属于函数,因此也可以对其进行函数重载,重载时,参数和参数数量均可改变:

#include <iostream>
#include <string>
using namespace std;template <class type>
type func_name2(type a, type b)
{type c = a - b;return c;
}template <class type>
type func_name2(type x, type b, type k)
{type y = k * x + b;return y;
}
int main()
{int get_c = func_name2(1, 2);double get_y = func_name2(2.0, 3.2, 2.0);cout << "get_c=" << get_c << endl;cout << "get_y=" << get_y << endl;
}

2、类中函数模板

2.1先在头文件的对应类中声明模板函数

class cls1
{
public:template<typename T>void func(T &args);
}

2.2在对应cpp文件中定义模板函数

    template<typename T>void cls1::func(T &args){函数体}

3、类模板

3.1 基本概念

格式:

template <template 类型名>

class 类名

{

public:

类型名 成员数据

成员函数(函数类型名 参数名)

}

当类模板中的成员函数需要在类外定义时,格式为:

template <typename 类型名>

函数类型名 类名<类型名>::成员函数名(类型名 形参表) {...}

示例:

#include <iostream>
#include <string>
using namespace std;template <typename num>
class compute
{
public:num a, b;compute(num x, num y) :a(x), b(y) {};num add();
};
template <typename num>
num compute<num>::add(){return a + b;
}int main()
{compute<int> result(2, 3);cout << result.add() << endl;
}

此外,类模板可以对模板类型指定默认类型,如:

template <typename TYPE=int>

class CLS{...}

注意:必须使用显示类型指导调用类模板进行实例化,否则类模板无法识别类型。当类模板有类型默认参数时,可以不实例化对应类型。

template <class Name_T,class Age_T = int>
class Person {
public:Person(Name_T name, Age_T age) {this->m_Name = name;this->m_Age = age;}void showPerson() {cout << "name:" << this->m_Name << " ";cout << "age:" << this->m_Age << endl;}private:Name_T m_Name;Age_T m_Age;
};int main() {//Person p1("马蒂", 22);//使用显示类型指导调用类模板进行实例化,否则类模板无法识别类型Person<string, int> p1("马蒂", 22);p1.showPerson();Person<string> p2("诺顿", 78);//当类模板有类型默认参数时,可以不实例化对应类型p2.showPerson();system("pause");return 0;
}

3.2 类模板中成员函数的创建时机

一般类中的成员函数是一开始就创建,而类模板中的成员函数在调用时才会被创建

如:下列代码可以生成成功,但在实际运行时必定会报错,这是因为类模板的成员函数在生成时并没有被创建,而发生调用后,才能被编译器检查到是否调用发生错误。

class P1 {
public:void func1() {cout << "P1" << endl;}
};class P2 {
public:void func2() {cout << "P2" << endl;}
};template <class T>
class TP {
public:T obj;void func3() {obj.func1();}void func4() {obj.func2();}
};int main() {TP<P1> p1{};p1.func3();p1.func4();system("pause");return 0;
}

3.3类模板实例化的对象作为函数参数

  a)指定传入的类型,直接显示对象的数据类型。

    b)将对象中的参数变成模板传入。

c)整个类模板化,将对象类型模板化进行传递。

template <class Name_T,class Age_T = int>
class Person {
public:Person(Name_T name, Age_T age) {this->m_Name = name;this->m_Age = age;}void showPerson() {cout << "name:" << this->m_Name << " ";cout << "age:" << this->m_Age << endl;}private:Name_T m_Name;Age_T m_Age;
};//指定传入的类型,直接显示对象的数据类型。
void func1(Person<string, int>& p) {p.showPerson();
}
//将对象中的参数变成模板传入。
template<class T1, class T2>
void func2(Person<T1, T2>& p) {p.showPerson();
}
//整个类模板化,将对象类型模板化进行传递。
template<class T_>
void func3(T_& p) {p.showPerson();
}

4、多类型模板

当需要返回的值的类型不确定时,可声明返回类型为auto(c++11),此时需要在函数体内使用decltype函数来获取返回值类型:

decltype(计算表达式)  self_typename

示例:

auto Quick_func::get_max(T1& a, T2& b){decltype(a > b ? a : b) out = a > b ? a : b;cout << "out:" << out << endl;return out;
}int main()
{int a = 20;double b = 115.0;typedef decltype(a > b ? a : b) outtype;outtype out = get_max(a, b);}

5、类模板与继承

a)如果父类是类模板,子类必须指定父类的参数类型。

b)如果想要同样灵活使用的父类的参数,将子类定义为类模板,指定子类的参数类型,将其作为继承到的父类参数类型即可。

示例:

template <class T>
class Base {T num;
};//指定子类的参数类型
class Son1 :public Base<float> {};//灵活使用模板参数
template<class T1,class T2>
class Son2 :public Base<T1> {T2 son2_param;
};

6、类模板成员函数类外实现与分文件编写

6.1 定义

类外实现:

当类模板的成员函数在类内声明,类外进行实现时,在实现部分中,必须加上类模板同样的template类型定义行,在普通类成员函数作用域的加上显示自定义类型使用,如:

template<class T>

void 类名<T>::函数名(T 形参)

{...}

分文件编写 :

        由于类模板中的成员函数是在调用时才会生成,因此如果只include写有类模板成员函数声明的头文件会报错,无法链接到成员函数定义。

解决方法:

a)直接在调用该成员函数的文件中包含写有类模板成员函数定义的cpp文件

        b)将类模板成员函数定义和声明写在同一个文件中,并将文件后缀改为hpp

6.2 示例

头文件:

template <class Name_T,class Age_T>
class Person {
public:Person(Name_T name, Age_T age);void showPerson();
private:Name_T m_Name;Age_T m_Age;
};

 函数声明文件:

#include "head1.h"template<class Name_T,class Age_T>
Person<Name_T, Age_T>::Person(Name_T name, Age_T age) {this->m_Name = name;this->m_Age = age;
}template <class Name_T, class Age_T>
void Person<Name_T, Age_T>::showPerson() {cout << "name:" << this->m_Name << " ";cout << "age:" << this->m_Age << endl;
}

main函数文件:

#include "head1.h"
#include "func1.cpp"
int main() {Person<string, int>* p = NULL;p = new Person<string, int>("Adam", 23);p->showPerson();delete p;system("pause");return 0;
}

7、类模板友元

a)类模板中可以定义友元全局函数,从而直接使用类模板的自定义数据类型。

b)当只在类模板中声明友元全局函数时,由于编译顺序原因,需要把该友元全局函数定义在类模板的前面,才能让类模板中的友元声明实现,而与此同时,由于友元全局函数定义时,将类模板作为传入参数,需要在该函数定义前“声明”一下有该类模板的存在,否则不能完成函数定义。

template <class Name_T, class Age_T>
class Person;template <class T1, class T2>
void printPerson2(Person<T1, T2>& p) {cout << "name:" << p.m_Name << " ";cout << "age:" << p.m_Age << endl;
}template <class Name_T,class Age_T>
class Person {//类内友元friend void printPerson1(Person<Name_T, Age_T> &p) {cout << "name:" << p.m_Name << " ";cout << "age:" << p.m_Age << endl;}//类外实现友元template <class T1, class T2>friend void printPerson2(Person<T1, T2>& p);
public:Person(Name_T name, Age_T age);void showPerson();
private:Name_T m_Name;Age_T m_Age;
};

c++模板(函数模板,类中函数模板,类模板)相关推荐

  1. 类中函数模板 typeof_Julia中的typeof()函数

    类中函数模板 typeof Julia| typeof()函数 (Julia | typeof() function) typeof() function is a library function ...

  2. python类中函数互相调用记得带self

    import time from selenium import webdriver import pymysql import uuid class  main (object): def  __i ...

  3. MFC类中获得其它类指针

    MFC类中获得其它类指针 从视图类获得文档类的指针是很容易的,用GetDocument即可,然而只能从视图类获得文档类的指针是远远不够的,每个类都有获得其它各个类指针的一套方法,本文归纳如下 AD: ...

  4. 重贴:MFC类中获得其它类指针 (转)

    重贴:MFC类中获得其它类指针 (转)[@more@] MFC类中获得其它类指针 成都:苏颖锋 (vcmfc输入并转贴) 当用VC++的Application Wizard生成除了CDialog Ba ...

  5. python中自定义类中的self_Python类和构造方法

    1.面向对象介绍 描述:是函数的一个变种,在Python中,有函数式编程和面向对象编程,java和C#之类只能把函数写到类里,没有函数式编程,所以只有面向对象,所以在Python中有了选择,可能就变得 ...

  6. 类中定义自身类的对象

    在C++的类定义中,是不能够在类中定义自身类的对象的,但是可以定义自身类的指针对象和引用. class A { public:  A ()  {   cout<<"Constru ...

  7. PetShop 4.0知识点:base 关键字用于从派生类中访问基类的成员

    //base 关键字用于从派生类中访问基类的成员: //调用基类上已被其他方法重写的方法. //指定创建派生类实例时应调用的基类构造函数. //基类访问只能在构造函数.实例方法或实例属性访问器中进行. ...

  8. python中arcsec_在Python类中继承Cython类

    我有两个用cython编写的类,我想在python中的一个类中使用它们.在 位置.pyximport numpy as np cimport numpy as np cimport cython cp ...

  9. string类有可以调换方向的函数吗_C++中的string类的用法小结

    相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC中的CString类使用起来真的非常的方便好用.但是如果离开了MFC框架,还有没有这样使用起来非常方便的类呢?答案是肯 ...

最新文章

  1. Python 的练手项目有哪些值得推荐?
  2. Infopath重复表分页(原创)
  3. 【商务智能】商务智能 ( 概念 | 组成 | 过程 )
  4. Unity开发者如何有效地进行本土化
  5. PCM设备能在公网使用吗?
  6. 【生成器】PHP的生成器yield【原创】
  7. 第四期coding_group笔记_用CRF实现分词-词性标注
  8. OpenCV的第一个小程序:读取图像并显示
  9. JPYXGSIT故障解决方案
  10. linux未找到telnet命令
  11. 使用NVivo完善定性编码的艺术
  12. 主板android刷机,安卓主板刷机步骤
  13. 做互联网最重要的是希望! 【水木周平】
  14. 数据结构之树家族介绍
  15. 哪款立体声骨传导蓝牙耳机好,推荐几款目前主流的骨传导耳机
  16. 基于JAVA中小学教师培训管理系统计算机毕业设计源码+系统+数据库+lw文档+部署
  17. 17.Rust中函数式语言功能:迭代器与闭包
  18. XCP实战系列介绍16-XCP标定过程指令解析
  19. 使用HorizontalListView仿车来了公交时刻表
  20. bravado哺乳内衣 这款哺乳胸罩,越早买越好,别等到下垂涨奶才知道后悔!

热门文章

  1. 下载!《Nacos 架构与原理》pdf
  2. python编程:从入门到实践(持续更新)
  3. C++产生随机数函数rand()
  4. 多线程相关实例(多线程经典应用场景)
  5. 拼多多商品详情接口,拼多多详情页接口,宝贝详情页接口,商品属性接口,商品信息查询,商品详细信息接口,h5详情,拼多多APP详情
  6. Verification和Validation
  7. 干货 | 深度学习之卷积神经网络(CNN)的模型结构
  8. 软件测试黑盒测试代码,软件测试黑盒测试代码.doc
  9. java登陆界面背景_Java登录界面的实现(注册、登录、背景图片)
  10. oracle数据库impdp命令的使用方法