c++面向对象——模板

模板

1. 模板:通用的模具

  • 特点:
    • 不可直接使用,只是一个框架
    • 模板的通用不是万能的
  • 作用:
    • 提高复用性
    • 将类型参数化

2 函数模板

  • 泛型编程主要利用的是模板

  • 两种模板机制:函数模板类模板

2.1 函数模板

  • 作用:建立一个通用函数,其函数返回值类型和形参类型可不具体定制,用一个虚拟类型来代表

  • 格式:

    template <typename T>
    //template 声明创建模板
    //typename 表示其后面的符号一种数据类型,可用class代替
    //typename 函数模板 class 类模板
    //T 通用的数据类型,名称可代替,通常为大写字母
    函数声明或定义
    
  • 使用方法

    • 自动类型推导(可根据变量类型自动推导)
    • 显示指定类型 函数名<typename>();
  • 注意:

    • 自动类型推导,必推导出一致的数据类型T,才可使用
    • 模板必须要确定出T的数据类型才可使用
  • 与普通函数的区别

    • 普通函数调用时可发生自动类型转换(意识类型转换)
    • 函数模板调用时,若利用自动类型推导,则不会发生饮食类型转换,若利用显示指定类型的方式,则可发生隐式类型转换
  • 调用规则

    • 若函数模板和普通函数均可实现,则优先调用普通函数
    • 可通过空模板参数列表来强制调用函数模板,即函数名<>(参数);
    • 函数模板也可发生重载
    • 若函数模板可更好地匹配优先调用函数模板(例普通函数需进行隐式类型转换,而模板可直接调用的话)
  • 局限性

    • 例1:赋值时,数组无法直接给数组赋值
    • 例2:自定义数据类型无法直接进行大小比较
  • 解决

    1. 运算符重载

    2. 利用具体化的模板

      //例
      template<> ReturnType 函数名(类型名 &t1,类型名 &t2){}
      

2. 类模板

2.1 类模板

  • 作用:建立一个通用类,类中成员数据类型可不具体制定,用一个虚拟类型来代表。

  • 格式

    template <typename T>
    //template 声明创建模板
    //typename 表示其后面的符号一种数据类型,可用class代替
    //typename 函数模板 class 类模板
    //T 通用的数据类型,名称可代替,通常为大写字母
  • 与函数模板的区别

    1. 类模板无自动类型推导

    2. 在模板参数列表中可有默认参数

      ClassName<参数类型1,参数类型2,...>t(参数1,参数2);
      //无论是参数类型还是参数均不可省略
      
  • 创建时机

    • 普通类的成员函数一开始就可以创建
    • 类模板中的成员函数在调用时才可创建

2.2 类模板对象做函数参数

  • 传入方式

    1. 指定传入类型 直接显示对象的数据类型

      ClassName<参数类型1,参数类型2,...>t(参数1,参数2,...);
      ReturnType 函数名(ClassName<参数类型1,参数类型2,...>&t){}
      
    2. 参数模板化 将对象中的参数变为模板进行传递

      template<class T1,class T2>
      ClassName<参数类型1,参数类型2,...>t(参数1,参数2,...);
      ReturnType 函数名(ClassName<T1,T2,...>&t){}
      
    3. 整个类模板化 将这个对象类型模板化进行传递

      template<class T>
      ClassName<参数类型1,参数类型2,...>t(参数1,参数2,...);
      ReturnType 函数名(T &t){}
      

2.3 类模板与继承

  • 注意:
    • 若子类继承的父类是一个类模板时,子类在声明时,要指出父类T的类型。若不指定,编译器无法给子类分配内存,若想灵活指定T的类型,子类也需变为类模板。

2.4 类模板成员函数类外实现

  • 构造函数的实现

    template<class T1,class T2>
    class ClassName{
        ClassName(T1 t1,T2 t2);
        ReturnType 函数名(参数);
    }
    
  • 普通成员函数的实现

    template<class T1,class T2>
    ClassName<T1,T2>::ClassName(T1 t1,T2 t2){}
    ReturnType ClassName<T1,T2>::函数名(参数){}
    

2.5 类模板分文件编写

  • 问题:类模板中的成员函数创建时机是在调用阶段,导致分文件编写时链接不到

  • 解决:

    • 解法1:直接包含.cpp源文件
    • 解法2:将声明和实现写在同一文件里,并更改后缀名为.hpp(并非强制)

2.6 类模板和友元

  • 全局函数类内实现——直接在类内声明友元

    friend ReturnType 函数名(ClassName<T1,T2> t){}
    
  • 全局函数类外实现——直需要提前让编译器知道全局函数的存在

    //首先得声名类
    template<class T1,class T2>
    class ClassName;
    //类外实现
    template<class T1,class T2>
    ReturnType 函数名(ClassName<T1,T2> t){}
    class ClassName{
        friend ReturnType 函数名(ClassName<T1,T2> t);
    }
    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值