问题来源:当模板文件的实现与声明分开在不同文件中时,链接时会提示找不到相应模板函数,如下

一,编译和链接的大概原理:

1,编译,遍历工程的所有代码文件,进行文件分析,这里的分析与文件后缀无关,并不是说以CPP文件为依据,源文件后缀名可以改为任何名字。

编译以文件为单位,将此文件#include的所有文件拿进来,写进此文件中,包含进来的东西可能是函数声明,也可能是函数的实现体。

如果#include "test.h",则包含进来的是一些函数和变量的声明,如果 #include "test.cpp",则其中的函数实现代码也被包含进来了。

编译的结果是一个obj文件,如test.cpp编译后是一个test.obj文件,里面是汇编指令。

同时,编译器有了该文件的一个清单,里面保存了 【函数签名(声明)】到【函数体实现】的映射

2,链接,对所有的obj文件进行拼接。

为什么要拼接?对于每个obj文件,其中若调用了其它文件的函数(外部调用),就需要知道此外部函数的具体实现,这在编译时是不关心的。

这时候去所有obj文件中查找此外部函数的实现体,若有两个以上的obj都有此实现,则链接出错,因为函数实现不唯一了,这不允许。此错误就是常见的

XXX 已经在 xxx.obj中定义了,如下:

若查找结果唯一,则将此外部函数的实现插入到调用处。

二,实例分析

1,一个头文件被多个CPP包含时编译链接正确,一个CPP文件被多个其它CPP文件包含时编译正确,链接出错,报错为 XXX 已经在 xxx.obj中定义。

因为CPP中有函数的实现体,每被包含一次就多了一个实现,导致一个函数在不同CPP文件中被多次实现,重复了。

头文件被多次包含为什么没问题?关键是每个头文件开头都有宏 #pragma once,该宏确保了头文件只会被包含一次

2,模板文件的特殊性。

模板文件只有在实例化时才能确定其具体的实现体,所以如果将模板文件的声明和函数体分开在.h和.cpp中,当编译cpp时,并不会产生函数的具体实现体。当在其它文件中#include "template.h"时,会提示找不到函数的定义。

解决方法:在需要使用模板函数的地方,#include "template.cpp",即包含它的CPP文件,而不是.h文件。

原因:使用模板函数的地方,比如 addobj<cube>(),传了具体的模板类型给函数,这样模板函数就能到CPP文件中找到对应的实现体将cube传给模板参数而实例化了。

3,综合的例子,若一个类中既有模板函数,又有非模板函数,那么只能将模板函数的声明与定义写在一个文件中,分开到两个文件是不行的。

C++模板声明与实现分开--由此想到的编译,链接原理相关推荐

  1. c++ 模板 声明与实现分开编写(error LNK2001: unresolved external symbol...)

    对于所有的喜欢把声明和定义分开放的C++er,在写模板时要把它俩放在一起一定感到十分郁闷,于是我本着非要棒打鸳鸯的倾向,找到了几种"棒"~ 欢迎各位完善棒打鸳鸯技巧~ 1.在模板的 ...

  2. c++模板声明与定义

    c++ 模板声明与定义 文章目录 c++ 模板声明与定义 前言 模板实例化 为什么C++编译器不能支持对模板的分离式编译 重点 C++模板代码的组织方式 --包含模式(Inclusion Model) ...

  3. 当年明月、袁腾飞、阎崇年三人的专业水平的比较以及由此想到的一些学习方法、品书原则

    以前听过一部分袁腾飞讲的<历史是个什么玩意儿>,也还凑乎.不过没再关注.直到最近听说他被封了,就找出来他的讲课记录听了听. 当年明月的<明朝那些事儿>基本是听的,几年前阎崇年在 ...

  4. error C2899: 不能在模板声明之外使用类型名称

    英文的真实描述为:"typename cannot be used outside a template declaration",由于翻译错误,将 typename 翻译成了 类 ...

  5. ora 00900 已编译但有错误_技术分享|万万没想到!编译错误竟然还没灭绝???

    CodeWisdom-技术分享 万万没想到!编译错误竟然还没灭绝??? 复旦大学CodeWisdom团队的代码分析和挖掘小组针对开源软件项目持续集成过程中出现的编译错误,进行了大规模的经验研究.该研究 ...

  6. 为什么C++模板声明与定义要放在同一文件中?

    写了3年多C++程序,很少用到模板,我靠,今天想试一下,照着别人的例子写,什么鬼,怎么都运行不过,仔细比对代码才发现,C++模板的声明与定义必须放到一个文件,.h或者.hpp, 真是颠覆我对C++编程 ...

  7. 双栏模板图片标题无法居中_没想到吧,只用一张图片,你就可以做一份PPT!

    ​hello,大家好啊,我是summer! 不知道大家有没有尝试过自己做一份PPT模板. 一般都会觉得素材太少,根本没办法做出一套. 其实并不是!PPT里面自带的形状.功能就足够我们做出一套好看的PP ...

  8. solidworks模板_工程师实用高级操作,Solidworks自定义属性链接到工程图模板

    下面,我以一个非常简单的零件为例,为大家介绍如何在工程图中链接这些属性.来达到减少工作量节省工作时间的目的. 1.这是1个简单的零件,零件的自定义零件属性都已经填写完成. 2.制作该零件的工程图文件, ...

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

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

最新文章

  1. WPF:Documents文档--Annomation批注(3)
  2. Java 13:切换表达式的增强功能
  3. java字体颜色编程_Java 字体颜色转换工具类 ColorUtil
  4. Ajax学习笔记-错误的处理-7
  5. 仿乐享微信源码分享,微信公众平台源码
  6. Android控件:在《第一行代码(第二版)》学习RecyclerView的踩坑经过
  7. spring定时器的使用
  8. 晶振的负载电容、寄生电容和动态电容及参考值
  9. 求n的阶乘问题。输入一个正整数n,输出n!
  10. python科学计算—— numpy
  11. FileInclude
  12. ArcGIS二次开发基础教程(11):网络分析之最短路径分析
  13. 分位数和分位线(Quantiles and Percentiles)
  14. Python初学者必看(1)
  15. Java 打卡Day-05
  16. docker与gosu-阿里云开发者社区
  17. 画四分之一玫瑰图-antvg2
  18. LIS3DH 3-axes digital accelerometer
  19. linux 中 vim/vi的常用命令
  20. 基于C++的车辆信息管理系统

热门文章

  1. 《系统集成项目管理工程师》必背100个知识点-43项目成本控制的主要内容
  2. 理解 Python 面向对象
  3. Java中使用Jedis连接Redis对Key进行操作的常用命令
  4. Winform中设置Dialog的显示位置居中
  5. UbuntuServer16.04LTS版怎样修改数据源为国内数据源
  6. Python中使用PIL快速实现二值图
  7. spring系列-注解驱动原理及源码-自动装配
  8. weblogic从入门到起飞!(受管服务器、免密启动、备份)(二)
  9. Dart 异步编程之 Isolate 和事件循环
  10. flutter利用高德如何获取地理位置信息bug处理