【问题标题】:Templated function being reported as "undefined reference" during compilation编译期间将模板化函数报告为“未定义引用”
【发布时间】:2010-10-07 05:16:10
【问题描述】:

这些是我的文件:

--------[ c.hpp ]--------

#ifndef _C
#define _C

#include<iostream>
class C
{
public:
    template<class CARTYPE> void call(CARTYPE& c);
};

#endif

--------[ c.cpp ]--------

#include "c.hpp"

template<class CARTYPE> void C::call(CARTYPE& c)
{
    //make use of c somewhere here
    std::cout<<"Car"<<std::endl;
}

--------[ v.cpp ]--------

class Merc
{};

--------[ main.cpp ]--------

#include "c.hpp"
#include "v.cpp"
//#include "c.cpp"

int main()
{
    Merc m; 
    C someCar;
    someCar.call(m);

}//main

我可以为上述所有文件生成“.o”文件,使用命令 g++ -c main.cpp 和 g++ -c c.cpp 等等。 但是当我尝试使用 g++ -o car c.o main.o v.o 链接“.o”文件时 我收到此错误:

main.o: In function `main':
main.cpp:(.text+0x17): undefined reference to `void C::call<Merc>(Merc&)'
collect2: ld returned 1 exit status

当我取消注释 main.cpp 中的 #include "c.cpp" 行时,错误消失了,但我觉得以这种方式包含 cpp 文件可能是不好的做法。我做错了吗?在创建单独的目标文件并链接它们时,是否有更好的方法来满足模板化声明? p.s:我在更复杂的类结构中使用模板化函数。此处显示的只是一个小示例,目的是向您展示我所面临的错误类型。

【问题讨论】:

标签: c++ templates makefile linker object-files


【解决方案1】:

我相信这是因为当你编译c.cpp时,编译器不知道它需要为C::call&lt;Merc&gt;(Merc&amp;)生成代码,而当你编译main.cpp时它没有C::call&lt;T&gt;(T&amp;)的定义从中实例化C::call&lt;Merc&gt;(Merc&amp;)

模板定义本质上是语义宏,与预处理器的#define 词法宏非常相似,它们必须在使用它们的编译单元中可见。

【讨论】:

    【解决方案2】:

    解决这个问题的方法是

    一个。从 c.cpp 中删除 '#include "c.hpp"' 并且

    b.在 'c.hpp' 的末尾包含 'c.cpp' (奇怪的声音 '#include "c.pp"')

    这样,模板定义可用于包含“c.hpp”的每个翻译单元,而无需在每个 .cpp 文件中明确这样做。这称为'inclusion model'

    【讨论】:

    • 如果您需要 c.cpp 中不应该包含在每个翻译单元中的内容,也会造成麻烦。
    • @Tony:哦,那你怎么办?
    • 那么您确实必须将模板实现移动到标题中。想想一个定义规则和所有的爵士乐......
    • @Tony:好的,然后在头文件中显式特化模板对吗?
    • 是的,所有模板实现必须在使用点可见,所以如果其他 cpp 使用特化,那么标题是共享它们的最佳位置(假设我们已经越界了放弃你开始的包容模型)。即使对于私有模板,不将专业化与通用实现本地化也会很混乱,所以我会说它们都在一起,无论是在 .h 还是 .cpp 中。
    【解决方案3】:

    本质上,在当前 C++ 中,您不能在单独的文件中拥有相关的模板声明和定义。您应该在一个文件中完整定义 C 类。

    【讨论】:

    • 澄清一下:这对于公共/受保护模板的常见和图解案例是正确的,但对于私有模板不是必需的。
    • 朋友类和私有模板会发生什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多