以下为个人推测。

对于一个普通的符号 f ,编译器对它做的事情如下:
(1) 编译时 :包含 f 定义(实现) 的源文件输送给编译器,编译器会编译相关代码并将结果打包到对应的 .o 里;
(2) 链接时 :当某处需要使用符号 f ,便 通过符号的声明寻找符号的实现 ,如果没找到某个符号的实现,就被报 undefined 错误。

对于非模版的符号,编译器会如上正常执行。

但对于模板类和模板函数,由于它的符号是抽象的,如 f<T>(T) A<T>::f() 中的 T 是未知的。
所以在 (1) 不会 把“ 符号 ”的实现打包到 .o (2) 时,实例化模板时,编译器才会看到 具体 的符号,如 f<double>(double) A<int>::f() ,但此时编译器需要知道符号的实现,因此会报 undefined 错误。

解决办法就是,把模板的定义和声明放在一个文件里。

template.h

#ifndef TEMPLATE_H
#define TEMPLATE_H
#include <iostream>
template <typename T>
void f(T);
template <typename T>
class A {
public:
    void f();
template <typename T>
void f(T)
    std::cout << "::f" << std::endl;
template <typename T>
void A<T>::f()
    std::cout << "A::f" << std::endl;
#endif

测试代码:
main.cpp

#include "template.h"
int main()
    f(3.14);
    A<int> a;
    a.f();
    return 0;

运行结果:
在这里插入图片描述
由于声明和定义写在了一起,在实例化模板时,通过符号的声明就能找到它的实现,因此链接不会出错。

对于一个普通的符号f,编译器对它做的事情如下:(1)编译时:包含f的定义(实现) 的源文件输送给编译器,编译器会编译相关代码并将结果打包到对应的.o里;(2)链接时:当某处需要使用符号f,便通过符号的声明寻找符号的实现,如果没找到某个符号的实现,就被报undefined错误。对于非模版的符号,编译器会如上正常执行。但对于模板类和模板函数,由于它的符号是抽象的,如f<T>(T)和A<T>::f()中的T是未知的。所以在(1)时不会把“符号”的实现打包到.o。(2)时,实例化模板时,编译器才会看到
本文实例为大家分享了C++利用链表模板类实现一个队列的具体代码,供大家参考,具体内容如下 设计思想:MyQueue.h中对模板类进行声明和实现。首先定义结点的结构体,包含数据和指针域两部分。队列类定义声明和实现了元素入队,出队,打印队首元素和队列等方法。 1)模板类的声明定义不能分开(即不能分别放在.h和.cpp文件里)。 2)声明新节点时,如果声明的节点是辅助操作的,可以不用new关键字,例如在析构函数中,直接用:Node<T>* temp;定义即可。如果声明一个新节点加入队列,则要用new关键字,否则会报出nullptr异常。 ​ConsoleApplication.cpp
问题起因是我在一个.h文件中定义模版类,忘了在.cpp中定义函数时如何写(就是忘了 CLASS::show中的),然后顺便在.h中声明了个模板函数(函数原型),又在cpp中定义,结果在主函数中用时,出现错误(未定义)。于是搜索,原来总结一句话如下 模版函数在.h中必须定义声明一块,都在其中。不能像普通函数一样,一个.h一个cpp,同样模板类的函数也不行,只是它可以在类中先声明,然后在类外
本文首发于我的公众号:码农手札,主要介绍linux下c++开发的知识包括网络编程的知识同时也会介绍一些有趣的算法题,欢迎大家关注,利用碎片时间学习一些编程知识,冰冻三尺非一日之寒,让我们一起加油! 说实话,我个人是不怎么使用模板的,使用场景很少,因此在上一篇博客里面难得用了一次模板,反而出了点小问题,我遇到的问题就是把声明和实现分开在h文件和cpp文件,因此在编译的时候怎么都无法通过,简直懵...
首先,C++标准中提到,一个编译单元[translation unit]是指一个.cpp文件以及它所include的所有.h文件,.h文件里的代码将会被扩展到包含它的.cpp文件里,然后编译器编译该.cpp文件为一个.obj文件,后者拥有PE[Portable Executable,即windows可执行文件]文件格式,并且本身包含的就已经是二进制码,但 当编译器将一个工程里的所有.cpp文件以...
首先明确的是: 对普通函数来说,声明放在头文件中,定义放在源文件中,其它的地方要使用该函数时,仅需要包含头文件即可,因为编译器编译时是以一个源文件作为单元编译的,当它遇到不在本文件中定义的函数时,若能够找到其声明,则会将此符号放在本编译单元的外部符号表中,链接的时候自然就可以找到该符号的定义了。 对于模板。先明确,模板函数是在编译器遇到使用模板的代码时才将模板函数实例化(之前只有函数的模板定义
写了3年多C++程序,很少用到模板,我靠,今天想试一下,照着别人的例子写,什么鬼,怎么都运行不过,仔细比对代码才发现,C++模板声明定义必须放到一个文件,.h或者.hpp, 真是颠覆我对C++编程的认知,什么坑爹的语法。网上找资料,看博客,看书,才知道必须这样写,太坑了。 例如我写的一个A 模板类,A.h文件: #pragma once #include &...
“通常情况下,你会在.h文件中声明函数和类,而将它们的定义放置在一个单独的.cpp文件中。但是在使用模板时,这种习惯性做法将变得不再有用,因为当实例化一个模板时,编译器必须看到模板确切的定义,而不仅仅是它的声明。因此,最好的办法就是将模板声明定义都放置在同一个.h文件中。这就是为什么所有的STL头文件都包含模板定义的原因。”[1] "标准要求编译器在实例化模板时必须在上下文中可以查看到其
[/code] 2.->*取的是类成员指针,[参考](https://stackoverflow.com/questions/6586205/what-are-the-pointer-to-member-operators-and-in-c) 指向4:root -> left -> right -> value = 4,和模板函数的参数有关