今天编码的时候,发现了一个错误,就是模板代码在链接的时候找不到方法。

情况大概如下:

在 "Manager.h" 中

class Manager {

public:

  template<typename T>

  void SetData(const T& value);

};

然后在cpp文件中定义SetData

template<typename T>

void Manager::SetData(const T& value) {

}

在另外一个main.cpp文件中使用

#include "Manager.h"

Manager mgr;

double n = 0;

mgr.SetData(n);

这样就会产生一个error LNK2019:无法解析的外部符号 “public: void __thiscall Manager::SetData<double>(const double&)” xxxx,该符号在 xx函数中被引用的链接错误。查了一下书籍,错误的原因在于,function template SetData(const T&)的定义没有具现化,Manager.h和Manager.cpp是分开编译的,在编译main.cpp的过程中,编译器假设这个template的定义在某个地方,因而只生成一个对该定义的reference,并将这个reference所指的定义式留给链接器去决议,但是在链接期间,又找不到这样一个定义。

Note:奇怪的是,如果n是int类型,又可以编译成功,但是回家后,我用自己的电脑试了一下,VS2008,int类型的也不行

解决这个问题有几个方法:

1)采用置入式。也就是定义也放在头文件中

2)显示具现化一份声明。

即在cpp文件中声明如下 template void Manager::SetData(const double&); ,这样做就要为每一个类型做一份声明,比较繁琐

3)采用export关键字。它会export出除inline之外的其他方法

export template <typename T>

class Manager {

public:

  void SetData(const T&); //这个声明就会被export

  void Print() {}; //不会被export

};

C++ template 声明与定义的更多相关文章

  1. c++函数模板声明与定义相分离

    最近在仿写stl,发现stl源码中将模板的声明与定义写在一起实在很不优雅.自己尝试用“传统”方法,及在.h文件里声明,在.cpp文件里定义,然后在main函数里包含.h头文件,这样会报链接错误.这是因 ...

  2. C++声明和定义

    目录 1 参考 2 概念 2.1 声明 2.2 定义 3 对比 3.1 声明但不是定义的情况 3.2 声明且是定义的情况 3.3 特殊情况 1. 参考 1. <C++程序设计语言>4.9 ...

  3. c++模板类成员的声明和定义

    c++模板类成员的声明和定义应该都放在*.h中,有普通类不一样. 如果定义放在*.cpp中,最终链接时,会报方法undefined错误. 参考:http://users.cis.fiu.edu/~we ...

  4. 为什么 c++中函数模板和类模板的 声明与定义需要放到一起?

    将模板的声明与定义写在一起实在很不优雅.尝试用“传统”方法,及在.h文件里声明,在.cpp文件里定义, 然后在main函数里包含.h头文件,这样会报链接错误.why!!!!!!!!!!!!! 这是因为 ...

  5. Error LNK2019: unresolved external symbol C++模板类声明与定义链接错误问题

    编译器在编译模板时,并不会生成代码,只有遇到实例化的时候才会生成代码.因此,当我们只引用模板声明文件的时候,在实例化的对象时候,模板的定义问文件是不可见的,于是出现链接错误.例如: //A.h #pr ...

  6. C++将模板的声明和定义放置在同一个头文件里

    1. 一个类: 头文件用于保存类的声明:定义文件保存类的实现.   2. 分离编译模式: 允许在一个编译单元(.cpp文件)中定义函数.类型.类对象等,然后在另一个编译单元中引用它们.编译器处理完所有 ...

  7. C++类模板声明与定义为何不能分开

    我们用C++写类的时候,通常会将.cpp和.h文件分开写,即实现和声明分开写了:但在C++的类模板中,这种写法是错误的. 在<C++编程思想>的第16章的"16.3模板语法&qu ...

  8. C++中重定义的问题——问题的实质是声明和定义的关系以及分离式编译的原理

    这里的问题实质是我们在头文件中直接定义全局变量或者函数,却分别在主函数和对应的cpp文件中包含了两次,于是在编译的时候这个变量或者函数被定义了两次,问题就出现了,因此,我们应该形成一种编码风格,即: ...

  9. C\C++中声明与定义的区别

    声明和定义是完全同的概念,声明是告诉编译器"这个函数或者变量可以在哪找到,它的模样像什么".而定义则是告诉编译器,"在这里建立变量或函数",并且为它们分配内存空 ...

随机推荐

  1. 输入值/表单提交参数过滤有效防止sql注入的方法

    输入值/表单提交参数过滤,防止sql注入或非法攻击的方法:  代码如下: /** * 过滤sql与php文件操作的关键字 * @param string $string * @return strin ...

  2. 你可能不知道的5个功能强大的 HTML5 API

    HTML5 新增了许多重要的特性,像 video.audio 和 canvas 等等,这些特性使得能够很容易的网页中包含多媒体内容,而不需要任何的插件或者 API.而其它的新元素,例如 section ...

  3. poj2421

    Constructing Roads Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 22048   Accepted: 93 ...

  4. 【BZOJ1899】[Zjoi2004]Lunch 午餐 贪心+DP

    [BZOJ1899][Zjoi2004]Lunch 午餐 Description 上午的训练结束了,THU ACM小组集体去吃午餐,他们一行N人来到了著名的十食堂.这里有两个打饭的窗口,每个窗口同一时 ...

  5. Leftmost Digit(hdu1060)(数学题)

    Leftmost Digit Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  6. (比赛)B - Super Mobile Charger

    B - Super Mobile Charger Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & ...

  7. 九度OJ 1261:寻找峰值点 (基础题)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:500 解决:37 题目描述: 给定一个整数序列,该整数序列存在着这几种可能:先递增后递减.先递减后递增.全递减.全递增. 请找出那个最大值的 ...

  8. Redis的主从同步手动执行故障切换

    1.准备三个redis配置文件,通过端口的区分,启动三个redis数据库实例,然后配置主从复制. # a6371.conf port 6371 daemonize yes pidfile /data/ ...

  9. Linux显示网络相关信息

    netstat -tlun    查看本机监听的端口 netstat -an      查看本机所有的网络连接 netstat -rn      查看本机路由表 -t TCP协议 -u UDP协议 - ...

  10. python+NLTK 自然语言学习处理五:词典资源

    前面介绍了很多NLTK中携带的词典资源,这些词典资源对于我们处理文本是有大的作用的,比如实现这样一个功能,寻找由egivronl几个字母组成的单词.且组成的单词每个字母的次数不得超过egivronl中 ...