读书笔记_Effective_C++_条款四十二:了解typename的双重意义
顾名思义,typename有双重含意。只要你用过template,那么第一重含意一定知道,那就是声明模板的时候,我们既可以这样写:
template <class T>
也可以这样写
template <typename T>
这两种写法并没有任何区别,都是标记T可以是符合隐式接口的任何类型,包括系统预定义类型,也包括用户自定义类型。
typename的第二重含意其实不大能遇到,因为这个依赖于编译器,看下面的例子:
class SampleClass
{
public:
typedef int MyInt;
// static const int MyInt = 3;
}; int main()
{
SampleClass::MyInt *b = new int(); // 有的编译器会报错
}
MyInt来源于SampleClass内的一个重定义,MyInt等价于int,所以main函数里面实质上是int *b = new int (3),但有的编译器会报error,这是因为编译器在遇到这句代码上会产生歧义,因为它可以将MyInt作为SampleClass的一个静态对象来看(可以看程序被注释掉的代码的地方),这样就变成了一个静态对象乘以b了。这种“看法”有些不可思议,但在有些编译器上,却是优先将之视为静态变量的,而不是类型。为了解决这个二义性,在前面加上typename,这样就会强制让编译器将之视为一个类型,而不是静态变量了。像这种SampleClass::MyInt或是书上举的T::const_iterator,都是类中定义的名字,这种名字称之为dependent names(嵌套从属名称),所有dependent names都潜在具有二义性,为了消除二义性,就在前面加上typename,变成typename T::const_iterator,typename SampleClass:MyInt,这样就会解决一些看似正确却怎么也编不过的代码问题了。
使用typename有两个特例,一个是继承的时候,像下面这样:
class A: public B::NestedClass{}; // 正确
class A: public typename B::NextedClass(){}; // 错误
在继承XXX类时,即使这个类名是dependent names,也不要使用typename,因为编译器这时候显示不会将之翻译成静态成员(被继承类必定是个类型)。
另一个特例是构造函数时,对于构造成员列表,像下面这样:
A(): B::NestedClass(){} // 正确
A(): typename B::NestedClass(){} // 错误
这时候编译器也不会将之视为静态对象的,因为静态对象是不支持成员初始化列表这样的初始化形式的,所以这时的typename,反而会被编译器认为一个是BUG。
最后总结一下:
1. 声明template参数时,前缀关键字class与typename可以互换
2. 请使用关键字typename标识嵌套从属类型名称;但不得在base class lists或者member initialization list内使用typename
读书笔记_Effective_C++_条款四十二:了解typename的双重意义的更多相关文章
- 读书笔记_Effective_C++_条款三十二:确定你的public继承继承塑模出is-a关系
这一条款是说的是公有继承的逻辑,如果使用继承,而且继承是公有继承的话,一定要确保子类是一种父类(is-a关系).这种逻辑可能与生活中的常理不相符,比如企鹅是生蛋的,所有企鹅是鸟类的一种,直观来看,我们 ...
- 读书笔记_Effective_C++_条款四十九:了解new_handler的行为
本章开始讨论内存分配的一些用法,C/C++内存分配采用new和delete.在new申请内存时,可能会遇到的一种情况就是,内存不够了,这时候会抛出out of memory的异常.有的时候,我们希望能 ...
- 读书笔记_Effective_C++_条款四十八:了解模板元编程
作为模板部分的结束节,本条款谈到了模板元编程,元编程本质上就是将运行期的代价转移到编译期,它利用template编译生成C++源码,举下面阶乘例子: template <int N> st ...
- 读书笔记_Effective_C++_条款四十六:需要类型转换时请为模板定义非成员函数
这个条款可以看成是条款24的续集,我们先简单回顾一下条款24,它说了为什么类似于operator *这样的重载运算符要定义成非成员函数(是为了保证混合乘法2*SomeRational或者SomeRat ...
- 读书笔记_Effective_C++_条款四十五:运用成员函数模板接受所有兼容类型
比如有一个Base类和一个Derived类,像下面这样: class BaseClass {…}; class DerivedClass : public BaseClass {…}; 因为是父类与子 ...
- 读书笔记_Effective_C++_条款四十四:将与参数无关的代码抽离template
标题上说“将与参数无关的代码抽离template”,这里的参数既可以指类型,也可以是非类型,我们先来看看非类型的情况. 假定我们要为矩阵写一个类,这个矩阵的行列元素个数相等,是一个方阵,因而我们可以对 ...
- 读书笔记_Effective_C++_条款四十:明智而审慎地使用多重继承
多重继承是一种比较复杂的继承关系,它意味着如果用户想要使用这个类,那么就要对它的父类也了如指掌,所以在项目中会带来可读性的问题,一般我们都会尽量选择用单继承去替代它. 使用多重继承过程容易碰到的问题就 ...
- 读书笔记_Effective_C++_条款三十:了解inline的里里外外
学过基本程序课的同学都知道,inline是内联的关键字,它可以建议编译器将函数的每一个调用都用函数本体替换.这是一种以空间换时间的做法.把每一次调用都用本体替换,无疑会使代码膨胀,但可以节省函数调用的 ...
- 读书笔记_Effective_C++_条款三十四:区分接口继承和实现继承
这个条款书上内容说的篇幅比较多,但其实思想并不复杂.只要能理解三句话即可,第一句话是:纯虚函数只继承接口:第二句话是:虚函数既继承接口,也提供了一份默认实现:第三句话是:普通函数既继承接口,也强制继承 ...
随机推荐
- 《区块链:从入门到放弃》之obc安装步骤
obc安装步骤 朋友们可能会好奇,厨师不研究菜谱怎么改研究兵法了,哈哈,我原本是app出身,最近被安排去预研区块链和比特币技术,2个月下来,颇有斩获.期间得到IBM的CC同学指导我一步一步安装obc的 ...
- iOS系统app崩溃日志手动符号化
iOS系统app崩溃日志手动符号化步骤: 1.在桌面建立一个crash文件夹,将symbolicatecrash工具..crash文件..dSYM文件放到该文件夹中 a.如何查询symbolicate ...
- C语言实现快速排序
我觉得冒泡排序是比较简单的: 所以今天我们实现一个叫做快速排序的: Problem 你想要将(4,3,5,1,2)排序成(1,2,3,4,5) 你决定使用最简单的快速排序: Solution 首先,打 ...
- atitit.条形码的原理与生成总结java Barcode4j barcode o5
atitit.条形码的原理与生成总结java Barcode4j barcode o5 条形码类库使用报告Barcode4j, ZXing 1 使用成果图片 1 条形码标准code 128和code ...
- javaweb回顾第七篇jsp
1:为什么会有JSP jsp全名(java server pages)中文叫做java服务器页面.在Servlet那一篇我们发现用Servlet可以生成动态页面,但是我们却在Servlet中却写了大量 ...
- word2007二级标题自动编号不从大标题开始的解决方法
今天在编写word文档的时候,遇到一个很奇怪的问题,word2007二级标题自动编号不从大标题开始,可能我说的比较模糊,我截个图大家一看就明白了. 我想要的是2.1 2.2结果,他确是从1.1开始了. ...
- 在gradle 中使用ant 执行 “命令行”(CMD)不出日志解决方案
因为gradle 好恶心,声明的任务,一定会事先运行一次,而任务追加的话就不会 例如: task hello(){ println "HelloWorld" } task hell ...
- C# inline-asm / 嵌入x86汇编
C#可不可以嵌入汇编 可以 在我眼中C#作为一个介于中上层语言是不可能不可以 置入汇编代码的 为什么会被我认为中上层语言呢 从C#保留指针就可以看出 我知 道有很多人一定不会相信C#可以使用汇编代码 ...
- 完全图解scrollLeft,scrollWidth,clientWidth,offsetWidth 获取相对途径,滚动图片(网上找的,未经试验,但觉得比较好)
获取元素的位置属性可以通过 HTMLElement.offsetLeft HTMLElement.offsetTop 但是,这两个属性所储存的数值并不是该元素相对整个浏览器画布的绝对位置,而是相对于其 ...
- linux red hat 安装svn
安装步骤如下: 1.yum install subversion 2.输入rpm -ql subversion查看安装位置,如下图: 我们知道svn在bin目录下生成了几个二进制文件. 输入 ...