C++模板、类模板、函数模板详解都在这里了

C++模板、类模板、函数模板详解都在这里了C 模板 类模板 函数模板详解一 引言二 函数模板 1 定义 2 调用 3 多个虚类型三 类模板 1 定义 2 调用四 类的函数模板五 类作为数据类型传入六 类模板与继承七 类模板与友元一 引言在写排序算法时 如果要写一个交换两个数据的函数 由于基本数据类型有 int float double 等等类型 所以针对每种数据类型可能我们要写很多 swap 函数 这些函数除了传入的数据类型不同 函数体结构大致相同

一、引言

在写排序算法时,如果要写一个交换两个数据的函数,由于基本数据类型有int、float、double等等类型,所以针对每种数据类型可能我们要写很多swap函数,这些函数除了传入的数据类型不同,函数体结构大致相同。所以C++为了避免让程序员写很多大量重复代码,设计了一种叫做“模板”的东西。我们写程序时,先不指定什么类型,在调用时我们再说明一下是什么类型,具体怎么实现接着往下看。

二、函数模板

1、定义

像开头所说,如果要对int、double类型的两个数进行交换我们要写两个函数,但用函数模板时只需要写一个函数即可。模板定义如下:

template

或者

template

其中,template是声明一个模板,typename是声明一个虚类型T,这个T可以代替int、double等基本数据类型,那为什么还有class?因为最初是用class声明一个T来表示通用数据类型,但考虑到class会和“类”混淆,就改用typename进行定义,同时保留了class,这两者效果相同,但我个人比较习惯用class。

在进行声明模板之后下面就开始写模板的函数体了,例如交换函数,合起来就是:

template <class T> void swap(T *p1,T *p2){ 
    T temp=*p1; *p1=*p2; *p2=temp; } 

这样就是一个完整的函数模板

2、调用

有两种方式使用模板

(1)自动类型推导:编译器会自动判定你传入的数据是什么数据类型,然后将T改成对应数据类型进行操作;

(2)自己声明数据类型进行调用,具体实现如下:

 //1、自动类型推导 swap(a, b); cout << "a=" << a << endl; cout << "b=" << b << endl; //2、显示指定类型 swap<int>(a, b); cout << "a=" << a << endl; cout << "b=" << b << endl; 

何时必须自己声明数据类型呢?

那就是没有参数传递的时候。比如知识一个打印函数,没有参数传递,这里就不写代码了。

3、多个虚类型

前面是针对一个函数里面都是同一数据类型的,如果含有不同数据类型,假如有两个:

template 
  
    void func(T1 a,T2 b){....} 
  

调用时可以自动识别类型也可以自己声明数据类型:

func 
  
    (1,3.14); 
  

三、类模板

前面已经介绍了模板大致的作用,这里对类模板就不做过多说明,直接上干货:

1、定义

我们定一个学生类

template<class T1,class T2,class T3> class Student{ 
    public: Student(T1 name,T2 age,T3 score){ 
    .......... } T1 m_Name; T2 m_Age; T3 m_Score; } 

2、调用

调用时必须指定输入了什么数据,也就是尖括号不能省略,这点与函数模板不一样

Student 
  
    s("Tom",18,85.5); 
  

四、类的函数模板

在类内定义的话就跟前面的函数模板一样,如果在类外定义,类外也要写上函数模板的形式:

template<class numType> class Compare{ 
    public: Compare(numType a,numType b){ 
    this->a=a; this->b=b; } //声明模板函数: numType max( ); private: numType a; numTypr b; } //类外定义模板函数 template<class numType> numType Compare::max( ){ 
    return this->a>this->b?this->a:this->b; } 

五、类作为数据类型传入

//定义Person1 class Person1 { 
    public: void showPerson1() { 
    cout << "Person1 show" << endl; } }; //定义Person2 class Person2 { 
    public: void showPerson2() { 
    cout << "Person2 show" << endl; } }; //定义类模板 template<class T> class MyClass { 
    public: T obj; //类模板中的成员函数 void func1() { 
    obj.showPerson1(); } void func2() { 
    obj.showPerson2(); } }; //主函数 int main() { 
    MyClass<Person1>m; m.func1(); //m.func2();//会报错,因为“showPerson2”: 不是“Person1”的成员 system("pause"); return 0; } 

六、类模板与继承

如果父类是一个模板,子类继承父类模板的时候,不知道父类模板内存是多少,编译器就无法给子类分配内存,解决方案是给子类也加上模板,方案如下:

template<class T> class Base { 
    T m_Name; }; //class Son :public Base { //错误,必须知道T的内存才能指定空间 class Son1:public Base<int>{ 
    // 不灵活 }; //想要灵活指定父类中T的类型 template<class T1,class T2> class Son2 :public Base<T2> { 
    public: T1 m_A; }; int main() { 
    //让子类的T为string,子类的T1为int Son2<int, string>s2; system("pause"); return 0; } 

七、类模板与友元

前面也有过传入类对象到函数里面,如果这个函数需要用到对象里面的数据,而该数据有被设定为private(私有)就无法直接访问,此时又要用到友元函数的知识:

注意:类内添加友元函数后,如果没有对该友元函数进行声明,编译器认为你没有这个函数,会进行报错。

//先声明类和函数,防止编译器报错 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 << "Name:" << p.m_Name << endl; cout << "Age:" << p.m_Age << endl; } 

觉得有用记得顶一下哦_

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/205591.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午5:40
下一篇 2026年3月19日 下午5:40


相关推荐

  • 一句话讲清楚什么是JavaEE「建议收藏」

    一句话讲清楚什么是JavaEE「建议收藏」Java技术不仅是一门编程语言而且是一个平台。同时Java语言是一门有着特定语法和风格的高级的面向对象的语言,Java平台是Java语言编写的特定应用程序运行的环境。Java平台有很多种,很多的Jav

    2022年8月3日
    9
  • 大四 Java开发实习近一年 记录(每6至12月更新一次)

    大四 Java开发实习近一年 记录(每6至12月更新一次)17年7月4号是我实习生入职的日子,因为是校企合作,所以没有面试、老师推荐、直接入职。刚来北京第一个感觉就是人多,还有就是热。刚到公司第一天,部门经理安排了我的mentor,他也是我的项目经理,安排座位之后给他我发了一些项目文档,让我先熟悉一下项目,然后给我发了几个常用工具的安装包,最重要的就是IDEA,之前在学校一直用MyEclipse,用了IDEA之后感觉确实不错,界面很漂亮。…

    2022年7月15日
    21
  • linux 进入编辑文件,保存退出相关命令「建议收藏」

    linux 进入编辑文件,保存退出相关命令「建议收藏」1.进入文件vim文件名(vimtest.txt)2.编辑完成之后,按ESC键跳到命令模式(命令前面冒号是必要的):  :w保存文件但不退出vi  :wfile将修改另外保存到file中,不退出vi  :w!强制保存,不推出vi  :wq保存文件并退出vi  :wq!强制保存文件,并退出vi  :q不保存文件,退出vi…

    2026年4月17日
    6
  • HTML常用标签和属性大全

    HTML常用标签和属性大全nbsp 目录 html 标签 lt 字体效果 区断标记 连结格式 贴图 音乐 表格语法 分割视窗 表单 表示颜色的有三种方式 属性可分为三种 align 属性 列表 nbsp 1 无序列表又称符号列表 2 有序列表 3 定义列表 name 连接名称 target 目标窗口语法格式 图像 nbsp 语法格式 font 元素 表格语法格式 tr 元素

    2026年3月18日
    0
  • 介绍一个EPG前端框架

    介绍一个EPG前端框架这是一个在原生 js 基础上开发的针对 iptv 行业的交互框架 参考了 android 的 Application 和 activity 实现整个页面的交互及生命周期

    2026年3月16日
    2
  • 千问插件使用教程与功能详解

    千问插件使用教程与功能详解

    2026年3月13日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号