1、关键字typename

引入关键字typename是为了说明:模板内部的标识符可以是一个类型。当某个依赖与模板参数的名称是一个类型时,就应该使用typename。

template<T>
class MyClass{typename T::SubType * ptr;  // typename说明SubType是定义于T内的一种类型,如果不使用typename,SubType会被认为是T的一个静态成员...
};

2、使用this->

对于那些在基类中声明,并且依赖于模板参数的符号(函数或变量等),应该在它们前面使用this->或者Base<T>::。

#include<iostream>
using namespace std;template<typename T>
class Base{
public:void exit(){ cout << "exit" << endl; }
};
template<typename T>
class Derived:Base<T>{
public:void exitDerived(){this->exit();//但VS 2013中直接用exit()也能正确运行}
};
int main(){Derived<int> d;d.exitDerived();system("pause");return 0;
}

3、成员模板

嵌套类和成员函数都可以作为模板,例子:

#include<iostream>
#include<deque>
using namespace std;template<typename T>
class Stack{
private:deque<T> deq;
public:void push(T const& elem);void pop();T top() const;bool empty() const{return deq.empty();}template<typename T2>//成员模板Stack<T>& operator=(Stack<T2> const& op2);
};
template<typename T>
void Stack<T>::push(T const& elem){deq.push_back(elem);
}
template<typename T>
void Stack<T>::pop(){if (deq.empty()){throw out_of_range("Stack<>::pop():empty stack");}deq.pop_back();
}
template<typename T>
T Stack<T>::top() const{if (deq.empty()){throw out_of_range("Stack<>::pop():empty stack");}return deq.back();
}
template<typename T>
template<typename T2>
Stack<T>& Stack<T>::operator=(Stack<T2> const& op2){if ((void*)this == (void*)&op2)return *this;Stack<T2> tmp(op2);deq.clear();while (!tmp.empty()){deq.push_front(tmp.top());tmp.pop();}return *this;
}int main(){try{Stack<float> istk;istk.push(7.2);istk.push(8.3);istk.push(9.4);cout << istk.top() << endl;istk.pop();cout << istk.top() << endl;Stack<int> sstk;sstk = istk;cout << sstk.top() << endl;sstk.pop();cout << sstk.top() << endl;}catch (exception const& ex){cerr << "Exception:" << ex.what() << endl;return EXIT_FAILURE;}system("pause");return 0;
}

4、模板的模板参数

模板参数本身是模板,则该参数是模板的模板参数。函数模板不支持模板的模板参数。

例子:

#include<iostream>
#include<deque>
#include<vector>
using namespace std;
//这里Container是模板的模板参数
template<typename T,template<typename ELEM,typename=allocator<ELEM>> class Container=deque>
class Stack{
private:Container<T> container;
public:void push(T const& elem);void pop();T top() const;bool empty() const{return container.empty();}template<typename T2, template<typename ELEM2, typename = allocator<ELEM2>> class Container2>Stack<T, Container>& operator=(Stack<T2, Container2> const& op2);
};
template<typename T, template<typename ELEM, typename = allocator<ELEM>> class Container>
void Stack<T,Container>::push(T const& elem){container.push_back(elem);
}
template<typename T, template<typename ELEM, typename = allocator<ELEM>> class Container>
void Stack<T, Container>::pop(){if (container.empty()){throw out_of_range("Stack<>::pop():empty stack");}container.pop_back();
}
template<typename T, template<typename ELEM, typename = allocator<ELEM>> class Container>
T Stack<T, Container>::top() const{if (container.empty()){throw out_of_range("Stack<>::pop():empty stack");}return container.back();
}
template<typename T, template<typename ELEM, typename = allocator<ELEM>> class Container>
template<typename T2, template<typename ELEM2, typename = allocator<ELEM2>> class Container2>
Stack<T, Container>& Stack<T, Container>::operator=(Stack<T2, Container2> const& op2){if ((void*)this == (void*)&op2)return *this;Stack<T2, Container2> tmp(op2);container.clear();while (!tmp.empty()){container.push_front(tmp.top());tmp.pop();}return *this;
}int main(){try{Stack<double> dstk;dstk.push(7.2);dstk.push(8.3);dstk.push(9.4);cout << dstk.top() << endl;dstk.pop();cout << dstk.top() << endl;Stack<int> istk;istk = dstk;cout << istk.top() << endl;istk.pop();cout << istk.top() << endl;}catch (exception const& ex){cerr << "Exception:" << ex.what() << endl;return EXIT_FAILURE;}system("pause");return 0;
}

5、使用字符串作为函数模板的实参

#include<iostream>
#include<string>
using namespace std;template<typename T>
T const& Max(T const& a, T const& b){return a < b ? b : a;
}int main(){string s = "abc";cout << Max("apple", "peach") << endl;//cout << Max("apple", "tomato") << endl;//错误,不同类型的实参//cout << Max("apple", s) << endl;//错误,不同类型的实参system("pause");return 0;
}

上述例子在VS2013中运行错误。

上述例子中后面两个调用错误的问题在于:由于长度的区别,这些字符串属于不同的数组类型,”apple”和”peach”具有相同的类型char const[6],”tomato”的类型是char const[7],因此只有第一个调用合法。但声明的是非引用参数,可以使用不同的字符串作为参数。

#include<iostream>
#include<string>
using namespace std;template <typename T>
T Max(T a, T b){return  a < b ? b : a;
}int main(){string s = "abc";cout << Max("apple", "peach") << endl;cout << Max("apple", "tomato") << endl;//正确,退化为相同的类型//cout << Max("apple", s) << endl;//错误,不同类型的实参system("pause");return 0;
}

上述第二个调用正确,原因是对于非引用类型的参数,在实参演绎的过程中,会出现数组到指针的类型转换。但是这里比较的是指针,而不是两个字符串的字典序。

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://www.cnblogs.com/ruan875417/p/4921345.html

【c++ templates读书笔记】【4】技巧性基础知识相关推荐

  1. 竞态条件的赋值_《Java并发编程实战》读书笔记一:基础知识

    一.线程安全性 一个对象是否是需要是线性安全的,取决于它是否需要被多个线程访问 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要额外的同步,这个 ...

  2. 《Java并发编程实践》学习笔记之一:基础知识

    <Java并发编程实践>学习笔记之一:基础知识 1.程序与进程 1.1 程序与进程的概念 (1)程序:一组有序的静态指令,是一种静态概念:  (2)进程:是一种活动,它是由一个动作序列组成 ...

  3. 【《Redis深度历险》读书笔记(1)】基础:万丈高楼平地起 ——Redis 5种基础数据结构

    [时间]2021.11.16 [题目][<Redis深度历险>读书笔记(1)]基础:万丈高楼平地起 --Redis 基础数据结构 本栏目是<Redis深度历险:核心原理和应用实践&g ...

  4. 前端学习笔记(js基础知识)

    前端学习笔记(js基础知识) JavaScript 输出 JavaScript 数据类型 常见的HTML事件 DOM 冒泡与捕获 流程控制语句 for..in 计时器 let,var,const的区别 ...

  5. LTE-V2X笔记:一些基础知识

    原文转载地址:LTE-V2X笔记:一些基础知识 (1)LTE-V2X技术 频段:5905~5925MHZ(试验频段) 调制方式:QPSK 正交相移键控 功率:23dBm (2)LTE-V2X通信模式 ...

  6. c++矩阵转置_lt;读书笔记4gt; 稀疏矩阵基础算法

    本篇为稀疏矩阵求解算法经典论著<Direct Methods for Sparse Linear System>的<读书笔记 4> Chapter 2 Basic algori ...

  7. 【读书笔记】Java基础学习之目录

    前述 :本人目前正在学习java,开发Android应用,因此重新来把java学习一遍. 本文所有资料来源于互联网,我将根据自己的学习进度,不断的将资料整合,就当作是读书笔记吧! 本文作为目录页,将不 ...

  8. 【学习笔记】网络安全基础知识总结

    网络安全基础知识总结 前言 一.网络安全概述 1.1 引言 1.2 密码学的发展 1.3 密码学基础 1.4 对称密码 1.4.1 数据加密标准DES 二.数论知识 2.1 数论基础 2.2 有限域 ...

  9. 【读书笔记】语言基础- Lua语言入门(一)

    目录 注:本系列为<Lua程序设计-第4版> 的读书笔记,其中的见解有不完善的地方,可以在评论区指出,原版请看图书 Lua运行环境 一. 使用Lua语言解释器运行Lua语言:(下面的实例以 ...

  10. JAVA学习笔记(1)【基础知识】

    JAVA学习笔记DAY_1 提示:关于java系列的内容只是本人在老师的指导下和自学过程中的一些学习笔记,如果存在错误敬请批评指正! 文章目录 JAVA学习笔记DAY_1 前言 一.Java语言未来的 ...

最新文章

  1. C++和服务器交互的几个文件代码
  2. 【多线程】C++11进行多线程开发 (std::thread)
  3. requirejs学习之-- 初始化(一)
  4. asp.net core中使用cookie身份验证
  5. MiniO对象存储服务 磁盘缓存快速入门 ​​​​​​​
  6. linux目录 31:1,Linux常用基础命令
  7. php鼠标 显示图片,鼠标放在图片上显示大图的JS代码
  8. 黑马程序员php考试题,PHP基础案例教程
  9. 忍不住笑的笑话(last:20180419)
  10. 组合优化问题MATLAB程序,组合优化问题(一).ppt
  11. Unable to start ServletWebServerApplicationContext due to missing ServletWeb
  12. SAP公有云和私有云解决方案概述
  13. sipp脚本撰写(二)
  14. 网络抓包-抓包工具tcpdump的使用与数据分析
  15. linux点用户输密码时就调回登录框,Linux系统登陆输入密码正确 闪回登陆界面
  16. MonoDETR:用于单目3D检测的深度感知transformer(CVPR2022)
  17. 世纪互联交付中心总监李少春:数据中心基础与服务探讨
  18. win10wifi间歇性断网重启后恢复_解决WIN10间歇性断网
  19. 如何检测文件中的违禁词和小于规定大小的文件?
  20. 兴业银行银企直连系统开发接口

热门文章

  1. 【编译器】Mac下gcc环境配置折腾
  2. linux 串口 dma,STM32 USART串口DMA 接收和发送流程详解
  3. linux git编译安装目录,Linux(centos) 环境下如何源码编译安装git
  4. spring boot @value取不到值_看看大厂如何自定义starter,还真想不到
  5. 七种方法实现单例模式
  6. 把合数分解成若干个质因数相成
  7. 面向对象的程序设计特点
  8. n皇后问题(在棋盘上找方案)
  9. RayMarching2:给球加上光照
  10. OpenGL基础12:进入3D世界