C++ 为什么分离模板定义/声明有时有效

C++ 为什么分离模板定义/声明有时有效,c++,C++,我凌晨1点就醒了,试图找出我遇到的编译错误。 我不能真正写出准确的代码,但我会尽我所能把我的问题说清楚 ClassWithTemplateFunction.hpp #include "StructA.hpp" #include "ClassB.hpp" class ClassWithTemplateFunction { template<typename A> void MyTemplateFunc(); } 结构a.cpp #include "ClassWithT

我凌晨1点就醒了,试图找出我遇到的编译错误。 我不能真正写出准确的代码,但我会尽我所能把我的问题说清楚

ClassWithTemplateFunction.hpp

#include "StructA.hpp"
#include "ClassB.hpp"
class ClassWithTemplateFunction
{
    template<typename A>
    void MyTemplateFunc();
}
结构a.cpp

#include "ClassWithTemplateFunction.hpp"
#include "StructA.hpp"
StructA::StructAFunc(ClassWithTemplateFunction* templ)
{
templ->MyTemplateFunc<SomeTemplate>();
}
类别b.cpp

#include "ClassB.hpp"
#include "ClassWithTemplateFunction.hpp"
void ClassB::ClassBFunc(ClassWithTemplateFunction* templ)
{
templ->MyTemplateFunc<SomeTemplate>();
}
#包括“ClassB.hpp”
#包括“ClassWithTemplateFunction.hpp”
void ClassB::ClassBFunc(ClassWithTemplateFunction*templ)
{
templ->MyTemplateFunc();
}

出于某种原因,现在引入了链接器错误(未定义对MyTemplateFunc()的引用)。我不明白为什么它突然产生了这个问题。显然,可以通过将定义移动到头文件来修复它,但我想了解,在添加ClassB之前,代码工作得很好。

如果
ClassWithTemplateFunction.cpp
以某种方式(例如通过调用它)实例化
MyTemplateFunc
,您将能够在程序中的任何位置使用与参数完全相同的
MyTemplateFunc

这就是为什么在第一种情况下不能得到未定义的引用


但是,在不同文件中使用完全相同的模板参数调用
MyTemplateFunc
不可能导致未定义的引用。请检查两种情况下的模板参数是否完全相同。

ClassWithTemplateFunction.cpp错误;至少它缺少
模板
。你说你“不能真正写出准确的代码”,但是如果你想要一个强有力的答案,你可以而且必须给出一个答案!帮助我们帮助你。看看。答案解释了为什么即使您违反了此规则,它仍适用于其中一种情况。@switwings未定义的引用错误是预期的行为。通常在这两种情况下你都会得到它。但是,如果模板在不同的CU中使用完全相同的参数进行了重新设置,它将起作用。这就是显式模板安装所做的。我可以理解,如果你的印象是,这段代码在正常情况下是有效的,那么它可能看起来有点令人困惑。@super我不明白你的意思。OP有两个几乎相同的TU,它们都不同于定义模板专业化的TU。其中一个据称会生成链接器错误,另一个则不会。那是没有道理的。如果是这样的话,我想你是有道理的。查看OP提供的代码,
StructA.cpp
中的用法应该给出一个未定义的引用错误。但事实并非如此。唯一可能的原因是OP在
ClassWithTemplateFunction.cpp
中进行了显式的模板安装,但忘记了提及它。更可能的解释是OP在
ClassWithTemplateFunction.cpp
中使用了与
StructA.cpp
中相同的类型参数,导致模板在该TU中不稳定。这导致没有任何未定义的引用错误。如果我正确阅读了问题,这与他们的发现正好相反。这没有道理。@asteroswings你对对立的定义似乎很奇怪…:-)@超级是吗?“然后我添加了一个新类[在一个新文件中],它也使用模板函数:[..],出于某种原因,这现在引入了一个链接器错误(未定义对MyTemplateFunc()的引用)。”正如@super提到的,我就是这样。感谢您的努力,我现在对模板函数有了更好的理解。
#include "ClassWithTemplateFunction.hpp"
#include "StructA.hpp"
StructA::StructAFunc(ClassWithTemplateFunction* templ)
{
templ->MyTemplateFunc<SomeTemplate>();
}
class ClassWithTemplateFunction;
class ClassB
{
void ClassBFunc();
}
#include "ClassB.hpp"
#include "ClassWithTemplateFunction.hpp"
void ClassB::ClassBFunc(ClassWithTemplateFunction* templ)
{
templ->MyTemplateFunc<SomeTemplate>();
}