news 2026/8/7 22:39:43

【C++面向对象】模板进阶用法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【C++面向对象】模板进阶用法

目录

      • 绪言
      • 实例化
        • 显式实例化
        • 隐式实例化
      • 特化
        • 全特化
          • 类模板全特化
          • 函数模板全特化
        • 偏特化
      • 多个模板参数
        • 缺省的模板参数
        • 带参数包的类型参数
      • 非类型模板参数

绪言

模板是泛型编程实现的重要手段。关于模板的基本用法,可以看我的这篇文章,这里不再过多地赘述。本篇文章主要是面向掌握了C++面向对象编程基本语法,希望深入学习的读者。建议大家根据自身情况自行选择阅读与否。

实例化

模板实例化是模板的重要概念。什么是实例化呢?在编写一个模板时,我们并没有具体指定模板类型参数,而是使用了一个占位符(例如T。而当我们在创建一个类模板对象,或者调用一个函数模板时,无论是显式指定模板类型参数,或者隐式推导,系统最终都会得到我们定义的占位符在调用时的具体指代。这个过程就叫做模板实例化

模板实例化分为显式实例化和隐式实例化,下面将分别讲述。

显式实例化

显式实例化,即手动指定模板中的类型参数,一般放在尖括号<>内,置于函数名之后调用函数模板,或者置于类名之后创建类模板对象。如果您还不能清晰地理解显式实例化,请看下面的实例:

#include<iostream>usingnamespacestd;template<typenameT>classmyclass{public:myclass(){};myclass(intp):id(p){};~myclass(){};public:intid;myclass<T>operator+(constmyclass<T>&b){myclass<T>ret(this->id+b.id);returnret;}};template<typenameT>Tadd(T a,T b){returna+b;}intmain(){myclass<int>a(5);myclass<int>b(6);cout<<add<myclass<int>>(a,b).id<<endl;return;}

运行上面的代码,将会输出以下结果:

11

观察main()函数,函数的一、二两行各定义了一个类模板对象,我们显式地用int类型代替了占位符T;函数的输出行调用了模板函数add,我们显式地用类型myclass <int>代替了占位符T。在这个实例中我们都显式地指定了类型参数。这就是显式实例化。

隐式实例化

与显式实例化相对的是隐式实例化。隐式实例化即不明确指定类型参数,而是系统通过函数的参数来推导类型参数。所以请注意:由于定义一个类模板对象时不一定都有参数可供推导,所以在C++标准中,隐式实例化是模板函数的专利,不能用于类模板。这也就告诉我们,一个类模板的名称并不是类型名,一个指定了类型参数的类模板名称才是类型名,例如在上面的实例中,myclass是非法的类型名,而myclass <int>是合法的。

隐式实例化不必指定类型参数,请看下面的实例,它与上面的实例是等价的

#include<iostream>usingnamespacestd;template<typenameT>classmyclass{public:myclass(){};myclass(intp):id(p){};~myclass(){};public:intid;myclass<T>operator+(constmyclass<T>&b){myclass<T>ret(this->id+b.id);returnret;}};template<typenameT>Tadd(T a,T b){returna+b;}intmain(){myclass<int>a(5);myclass<int>b(6);cout<<add(a,b).id<<endl;}

相比于之前的实例,这里只是把函数add()的调用更改了一下,去除了函数名之后指定类型参数的内容。这就是隐式实例化。

特化

与模板实例化相似的概念还有模板特化。模板特化,就是对于特殊的模板类型参数,我们想实现不同的功能时补充的专门性的函数。特化分为全特化和偏特化。

全特化

全特化的一般形式为:

类模板全特化
template<typenameT>classa{public:T ori;//class body};template<>classa<constchar*>{public:constchar*ori;//class body};
函数模板全特化
template<typenameT>Tadd(T a,T b){returna+b;}template<>charadd<char>(chara,charb){returna+b;}
偏特化

由于函数模板的偏特化可以通过重载实现,所以函数模板没有偏特化,只有类模板有偏特化。

template<typenameT1,typenameT2>classa{public:T1 ori1;T2 ori2;//class body};template<typenameT>classa<constchar*,T>{public:constchar*ori1;T ori2;//class body};

多个模板参数

模板参数可以不止一个。例如在上面的实例中,类a中就有两个类型参数T1T2。在含有多个模板参数的模板参数列表中,与函数参数类似地,每个参数之间用,隔开。

缺省的模板参数

模板参数也可以缺省,但所有缺省参数只能放在普通参数之后模板参数可以只含有缺省参数,但即使如此,类模板对象创建时也要加上尖括号<>。请看下面的实例:

template<typenameT1=int,typenameT2=int>classa{public:T1 A;T2 B;public:a(){};a(T1 first,T2 second):A(first),B(second){};~a(){};};intmain(){a<>Classa;a<char>Classb;a<double,double>Classc;return0;}
带参数包的类型参数

在类型参数列表中的typenameclass关键字后加上运算符...可以声明一个类型参数是参数包类型,即该类型带有参数包。这样写的好处是可以与可变参数相结合编程。以下是一个实例:

#include<vector>#include<type_traits>#include<iostream>usingnamespacestd;template<typenameT>classmyclass{private:vector<T>ori;public:myclass(){};template<typename..._Args>myclass(_Args...args){vector<T>tmp{forward<T>(args)...};this->ori=tmp;}~myclass(){};public:voidprint(){for(inti=0;i<this->ori.size();i++){cout<<ori[i]<<' ';}cout<<endl;return;}};intmain(){myclass<int>a{1,2,3,4,5};a.print();return0;}

运行上面的代码,将会输出以下结果:

1 2 3 4 5

非类型模板参数

模板的参数不一定必须是类型参数,也可以像函数参数一样是一个具体的对象。以下是一个实例,展现了模板非类型参数实现变长数组的方法:

#include<iostream>usingnamespacestd;template<typenameT,size_t N>classarr{private:T ori[N];public:arr(){memset(ori,0,sizeof(ori));}~arr(){};};intmain(){arr<int,5>a;return0;}

这里模板参数N就不是类型参数,而是一个size_t类型的变量。调用时也与一般的类模板相同,将模板参数置于尖括号<>内。

希望大家多多支持!多评论、多点赞、多收藏、多关注!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/7 22:37:01

Akagi智能麻将AI分析工具:从新手到高手的完整实战指南

Akagi智能麻将AI分析工具&#xff1a;从新手到高手的完整实战指南 【免费下载链接】Akagi 支持雀魂、天鳳、麻雀一番街、天月麻將&#xff0c;能夠使用自定義的AI模型實時分析對局並給出建議&#xff0c;內建Mortal AI作為示例。 Supports Majsoul, Tenhou, Riichi City, Amats…

作者头像 李华
网站建设 2026/8/7 22:30:40

计算机操作系统23

第二十三课&#xff1a;内存管理基础一、为什么需要内存管理&#xff1f; 我们先回到计算机最基本结构。 一个程序&#xff1a; 比如&#xff1a; QQ.exe 浏览器.exe 游戏.exe它们存放在哪里&#xff1f; 答案&#xff1a; 硬盘。 例如&#xff1a; 硬盘↓程序文件但是&#xf…

作者头像 李华
网站建设 2026/8/7 22:28:02

揭秘自动驾驶制动系统:automated-driving-control校准方案

揭秘自动驾驶制动系统&#xff1a;automated-driving-control校准方案 【免费下载链接】automated-driving-control 项目地址: https://gitcode.com/gh_mirrors/au/automated-driving-control 在自动驾驶技术快速发展的今天&#xff0c;制动系统的精准控制直接关系到行…

作者头像 李华
网站建设 2026/8/7 22:27:06

FileBrowser深度解析:Go语言构建的轻量级Web文件管理实战指南

FileBrowser深度解析&#xff1a;Go语言构建的轻量级Web文件管理实战指南 【免费下载链接】filebrowser File Browser provides a file managing interface within a specified directory and it can be used to upload, delete, preview and edit your files. 项目地址: htt…

作者头像 李华