著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:余天升
链接:http://www.zhihu.com/question/20630104/answer/15722407
来源:知乎

谢@欲三更 邀,这个问题让我想起我在实习的时候犯的一个错误,就是把模版类的定义和实现分开写了,结果编译出错,查了两天才查出问题。

C++中每一个对象所占用的空间大小,是在编译的时候就确定的,在模板类没有真正的被使用之前,编译器是无法知道,模板类中使用模板类型的对象的所占用的空间的大小的。只有模板被真正使用的时候,编译器才知道,模板套用的是什么类型,应该分配多少空间。这也就是模板类为什么只是称之为模板,而不是泛型的缘故。

既然是在编译的时候,根据套用的不同类型进行编译,那么,套用不同类型的模板类实际上就是两个不同的类型,也就是说,stack<int>和stack<char>是两个不同的数据类型,他们共同的成员函数也不是同一个函数,只不过具有相似的功能罢了。&amp;lt;img src=&quot;https://pic2.zhimg.com/1772de8abdd112a50e533e3c018535a1_b.jpg&quot; data-rawwidth=&quot;749&quot; data-rawheight=&quot;308&quot; class=&quot;origin_image zh-lightbox-thumb&quot; width=&quot;749&quot; data-original=&quot;https://pic2.zhimg.com/1772de8abdd112a50e533e3c018535a1_r.jpg&quot;&amp;gt;如上图所示,很简短的六行代码,用的是STL里面的stack,stack&amp;amp;lt;int&amp;amp;gt;和stack&amp;amp;lt;char&amp;amp;gt;的默认构造函数和push函数的入口地址是不一样的,而不同的stack&amp;amp;lt;int&amp;amp;gt;对象相同的函数入口地址是一样的,这个也反映了模板类在套用不同类型以后,会被编译出不同代码的现象。如上图所示,很简短的六行代码,用的是STL里面的stack,stack<int>和stack<char>的默认构造函数和push函数的入口地址是不一样的,而不同的stack<int>对象相同的函数入口地址是一样的,这个也反映了模板类在套用不同类型以后,会被编译出不同代码的现象。

所以模板类的实现,脱离具体的使用,是无法单独的编译的;把声明和实现分开的做法也是不可取的,必须把实现全部写在头文件里面。为了清晰,实现可以不写在class后面的花括号里面,可以写在class的外面。

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:缪天翔
链接:http://www.zhihu.com/question/20630104/answer/50856786
来源:知乎

这个feature叫做Export Template,即外名模板,它的作用在于使得模板代码可依照C/C++语言习惯,将模板声明和实现分开分别放到.h和.cpp文件中,并且可以减少冗长的模板编译时间(否则同一模板实例需要在不同编译单元中分别实例化)。

Export Template曾经是被写入C++98标准中的,然并卵,很少有主流编译器支持这一特性。在最新的C++11标准中,它已经被除名了,代之使用extern关键字阻止编译器在某编译单元内实例化特定模板。

Export Template的实现原理,摘录自《深入实践C++模板编程》。

在编译main.cpp时,como的处理与其他编译器并无太大差异,也是生成一个对square<float>的调用等待链接。而在编译square.cpp时,由于square模板声明是一个外名模板,虽然como不会为其生成任何模板实例代码,但是会额外生成一个square.et文件,其中包含对square函数模板实现的索引信息。之后进入一个预链接(prelink)阶段。在此阶段,编译器将根据之前编译时发现的对模板实例的需求,从所有et文件中查找到所需模板实现所在代码文件(cpp文件),并重新编译出所需模板实例。例如例1.8中,在main.cpp中调用了square<float>。那么como将从square.et文件中找到模板square的实现在文件square.cpp中,然后重新编译square.cpp以生成square<float>供链接使用。随后的链接过程和其他C++编译器类似,最终形成链接完整的可执行文件。

有点类似于C++编译器处理全局类对象实例构造的过程,它们需要在main函数之前构造好。

而现代编译器通常的模板实现方式是在编译单元当场生成实例,随后在链接时从重复实例中随机挑选一个进行链接。然而为了支持Export Template,需要对现有编译器做出巨大改动。从人力时间成本考虑,并且有work around可替代方法,Export Template最终被大部分编译器抛弃了。

于是C++的模板库,一定是开源的^ ^

C++ 中的模板类声明头文件和实现文件分离后,如何能实现正常编译?相关推荐

  1. c++模板类声明和定义的问题

    这里在学习的过程中遇到的一些问题,比较简单,但还是记下来,以免下次遇到这个问题再犯,大佬们可跳过哦.先简单的介绍下模板的概念 C++模板(泛型编程) c++模板是泛型编程的基础,所谓泛型编程也是一种思 ...

  2. C++模板类声明和定义几种写法

    为什么模板类的实现放在cpp会出错 在编译用到了模板类的编译单元时,编译器需要访问方法或者类的实现,以实例化它们. 如果这些实现不在头文件中,则它们将不可访问,因此编译器将无法实例化模板,进而会导致编 ...

  3. STL中的模板类pair 和map http://blog.csdn.net/calvin_zcx/article/details/6072286

    STL中的模板类pair 和map 分类: 我的c++心得2010-12-13 00:45 5237人阅读 评论(0) 收藏 举报 pairiostreamiteratorstringfloatbas ...

  4. STL中的模板类map的介绍

    STL中的模板类map的介绍 佟强 2008.11.5 map的元素是由key和value两个分量组成的对偶(key,value).key是键,value是与键key相关联的映射值.元素的键key是唯 ...

  5. C++ 模板类与头文件

    今天将模板类函数分成了声明和定义两个文件: 模板类的声明: #pragma once#ifndef FIND_ITEM #define FIND_TIEM template <typename ...

  6. c语言程序中变量先引用声明,C语言如何跨文件调用函数定义中声明的变量

    变量的作用域 我们知道,变量根据其作用域有全局变量和局部变量之分.全局变量作用域是整个文件,并且可以使用关键字 extern 达到跨文件调用的目的.但是局部变量值作用于它当前所在的块(即该变量所处最内 ...

  7. 如何在Eclipse中生成Native类对应的JNI的.h文件

    1 致谢 感谢super_level网友 他的博客写的很清楚 给了我很多帮助 链接如下:http://blog.csdn.net/super_level/article/details/2124353 ...

  8. 学习笔记-----关于VS中使用模板类出现无法解析的外部符号问题

    最近再学数据结构,刚接触线性表,用VS2015照着书把linearList的array描述补全了结果运行总提示:无法解析的外部符号 翻了几篇博客发现貌似是和C++编译的机制有关(底层机制不是很懂,(- ...

  9. 在类模板的声明和定义中把.h与.cpp分离

    看了几位大吓的回复,深深地感觉到了这篇附笔中可能存在错误,于是把最初遇到此问题时的环境再模拟了一下,现在可以确认这篇附笔中的确存在问题,现在就修正一下,并对各位表示歉意. 6月初的一个项目中需要写一个 ...

最新文章

  1. 【JAVA零基础入门系列】Day2 Java集成开发环境IDEA
  2. 光伏电站或成辅助服务市场“输家”
  3. 学python用哪个软件-学python要准备什么软件-问答-阿里云开发者社区-阿里云
  4. 每日一记--2014.9.22
  5. lightroom安卓_安卓可以用的一款PS
  6. 【模型开发】构建风控评分卡模型介绍(WOE/KS/ROC)
  7. SalesOrder Text determination
  8. java如何读取自定义log4j2_spring boot自定义log4j2日志文件的实例讲解
  9. 使用Java编写简单的老虎机游戏
  10. 2018.09.14python学习第四天part2
  11. linux进程map,LInux环境运行mapReduce程序
  12. zoiper 软件_zoiper软件下载
  13. 北京内推 | 微软亚洲研究院机器学习组招聘NLP/语音合成等方向全职研究员
  14. ZT华尔街日报:中国楼市泡沫的破灭预言 暴跌70%
  15. 【Spring Security Oauth2】构建资源服务器(二):授权管理(Web授权,注解授权:securedEnabled, prePostEnabled, jsr250Enabled)
  16. 0045-量化第十天:QMT-以DMA指标为例调用系统指标
  17. js实现手机端摇一摇
  18. 嵌入式系统C语言编程基础
  19. 第22章 迈向Spring MVC的旅程
  20. 基于php+Mysql网上商城系统 开题报告

热门文章

  1. 转:优化js脚本设计,防止浏览器假死
  2. TortoiseGit密钥的配置
  3. Screenlets:桌面小玩意
  4. 学python语言用什么软件-对于自学python的初学者来说,应该使用什么编辑工具?...
  5. python第三方库有哪些常用的、请列举15个-你想要的Python面试都在这里了【315+道题】...
  6. python零基础入门教程学习要多久-廖雪峰python教程要学多久-零基础学Python需要多久...
  7. python读文件操作-python 之文件操作
  8. python字符串find函数-python字符串查找函数的用法详解
  9. python读音有道词典-有道词典命令行快速翻译,Python编程的利器
  10. 精通python设计模式-精通Python设计模式