
C++模板编程与泛型编程之类模板、变量模板、别名模板(一)
发布日期:2021-05-07 15:12:22
浏览次数:15
分类:技术文章
本文共 3012 字,大约阅读时间需要 10 分钟。
类模板的基本范例和模板参数的推断
-
类模板
- 是产生类的模具,通过给定的模板参数,生成具体的类,也就是实例化一个特定的类。
- 例如vector<int>,引入类模板的目的,减少代码冗余
- 基本范例
- myvector可以称为类名或者类模板
- myvector<T>可以称为类型名(myvector后面带了尖括号,表示的就是 一个具体类型了)
- 类模板定义
template//T是类型模板参数,表示myvector这个容器所保存的元素类型class myvector //myvector可以称为类名或者类模板 , myvector 可以称为类型名(myvector后面带了尖括号,表示的就是 一个具体类型了){public: typedef T* myiterator; //迭代器public: myvector(); //构造函数 //myvector& operator=(const myvector&); //赋值运算符重载 myvector & operator=(const myvector&); //赋值运算符重载public: void myfunc() { cout << "myfunc()被调用" << endl; } static void mystaticfunc() { cout << "mystaticfunc()被调用" << endl; }public: //迭代器接口 myiterator mybegin(); //迭代器起始位置 myiterator myend(); //迭代器结束位置};
- 类模板实现
templatemyvector ::myvector() //类外构造函数的实现{}
- 类模板调用
myvector tmpvec; //T被替换成了inttmpvec.myfunc(); //调用普通成员函数
- 类模板中,只有被调用的成员函数(包括静态成员函数),编译器才会产生出这些函数的实例化代码
案例1:执行调用
myvector tmpvec; //T被替换成了inttmpvec.myfunc(); //调用普通成员函数
- 验证:
- 将源文件编译生成 .obj 文件,然后利用dumpbin反汇编
- 查看结果
案例2:不执行调用
myvector tmpvec; //T被替换成了int//tmpvec.myfunc(); //调用普通成员函数
- 验证:
- 将源文件编译生成 .obj 文件,然后利用dumpbin反汇编
- 查看结果
模板参数的推断
- C++17中,类模板的类型模板参数也能推断了。
- 在上面案例中加入带参构造函数代码,如下
templateclass myvector {public: myvector(); //构造函数 myvector(T tmpt) { }}
- 调用时,不指定类型,由编译器自动推导
myvector tmpvec2(12); //无需指定模板参数了//不用写成//myvector tmpvec2(12); tmpvec2.myfunc(); //调用类模板中的普通成员函数
推断指南(deduction guide)概要了解(引导编译器推断)
- c++17新概念:主要用来在推断类模板参数时提供推断指引。
-
隐式的推断指南
- 针对类模板A的每个构造函数,都有一个隐式的模板参数推断机制存在,这个机制,被称为隐式的推断指南
templatestruct A{ A(T val1, T val2) { cout << "A::A(T val1,T val2)执行了!" << endl; } A(T val) { cout << "A::A(T val)执行了!" << endl; }};
- 调用
//A aobj1(15, 16);A aobj1(15, 16); //A A aobj2(12.8); //A
- 推断指南解析:
- 推断指南样式如下:
templateA(T,T)->A ;
- 出现 -> 左侧部分内容或者形式时,请推断成 -> 右侧的类型。
- 右侧类型也被称为“指南类型”
- -> 左侧部分:该推断指南所对应的构造函数的函数声明,多个参数之间用,分隔。
- -> 右侧部分:类模板名,接着一个尖括号,尖括号中是模板参数名。
- A(T,T)->A<T> 的含义:
- 当用调用带两个参数的构造函数通过类模板A创建相关对象时,请用所提供的构造函数的实参来推断类模板A的模板参数类型,
- 一句话:推断指南的存在意义就是让编译器能够把模板参数的类型推断出来。
- 备注:
- 像这样是无法推断出A的模板参数,报错
A* aobj3 = NULL
- 此时需要指定类型int
A * aobj3 = NULL
自定义的推断指南
- 在类定义后面进行自定义推断指南
templatestruct A{ A(T val) { cout << "A::A(T val)执行了!" << endl; }};template A(T)->A ;
- 调用结果如下:
A aobj2(13.14); //A
- 没有构造函数,就没有隐式地推断指南
templatestruct B{ T m_b;};
- 此时必须指定类型
::B bobj1; //需要明确指定模板参数类型::B bobj2{15}; //可以用初始化列表的方式来定义对象bobj2,成员变量m_b=15。
- 在没有构造函数,就没有隐式地推断指南的情况下指定推断指南
templatestruct B{ T m_b;};template B(T)->B ;
- 此时能推导出类型,如下
B bobj3{ 15 };
- B bobj3{ 15 }不报错的原因
- 类B是聚合类。 是可以通过 {} 初始化的
- B bobj3{ 15 }这种形式正好就相当于调用了类模板B的带一个参数(15)的构造函数,尽管类模板B中实际并不存在构造函数。
- 因为 template<typename T> B(T) -> B<T>;
- 推断指南的存在,当调用了类模板B带一个参数的构造函数时,推断出来的类型为B<T>,所以最终推断出来的类型为B<int>类型。
- 如果需要针对两个参数,如下
B bobj4{ 15,20 };
- 则需要增加两个参数的推导指南
templatestruct B{ T m_b; T m_b2;};template B(T)->B ;template B(T,T)->B ;
发表评论
最新留言
感谢大佬
[***.8.128.20]2025年04月11日 18时20分01秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
医疗管理系统-手机快速登录和SpringSecurity权限控制
2019-03-04
vue源码分析(MVVM篇)
2019-03-04
React(八)- ReactUI组件库及Redux的使用
2019-03-04
TypeScript系列文章导航
2019-03-04
Java中Map的用法详解
2019-03-04
base64编码字符串和图片的互转
2019-03-04
汉字转为拼音
2019-03-04
linux 下安装kolla报错 提示Cannot uninstall requests
2019-03-04
设计模式之组合模式
2019-03-04
(恋上数据结构笔记):优先级队列(Priority Queue)
2019-03-04
(Python学习笔记):字典
2019-03-04
(C++11/14/17学习笔记):并发基本概念及实现,进程、线程基本概念
2019-03-04
(C++11/14/17学习笔记):线程启动、结束,创建线程多法、join,detach
2019-03-04
leetcode 14 最长公共前缀
2019-03-04
做做Java
2019-03-04
map的find函数和count函数
2019-03-04
C++并发与多线程(一)
2019-03-04
7628 EDCCA认证寄存器修改(认证自适应)
2019-03-04