未定义对模板库成员函数的引用 class

Undefined reference to member function of template base class

考虑以下代码:

myclass.h :

template <class T>
struct S {
    void f();
};

struct MyClass : public S<int>
{
    void g();
};

myclass.cpp :

#include "myclass.h"
#include <iostream>

template <class T>
void S<T>::f()
{
    std::cout << "f()\n";
    /* some code here that could not be in header */
}

void MyClass::g()
{
    std::cout << "g()\n";
}

main.cpp :

#include "myclass.h"

int main()
{
    MyClass m;
    m.g();
    m.f(); // problem here
}

我遇到链接器错误:

undefined reference to `S::f()'

我可以在不将 S::f() 的实现转移到头文件的情况下解决这个问题吗? 为什么 S::f() 在我声明从完全专用模板库 class 派生的 MyClass 时未实例化?

如果不将 s::f() 函数的实现转移到头文件中,您将无法解决此问题。这是因为编译器在使用模板之前必须知道模板的实现。

Why S::f() not instantiated when I declare a MyClass derived from full specialized template base class?

因为您的 myclass.cpp 没有使用该模板,并且像翻译单元中所有未使用的模板一样,它们在生成的代码中毫无意义。推导一切都很好,如果 MyClass::g() 使用 S<T>::f() 你会引入该代码,生活会很美好。但是你没有,所以你必须换一种方式来拉它......

您应该能够通过显式实例化来做到这一点。请注意您的 .cpp 文件中的以下内容:

#include "myclass.h"
#include <iostream>

template <class T>
void S<T>::f()
{
    std::cout << "f()\n";
}

void MyClass::g()
{
    std::cout << "g()\n";
}

template struct S<int>; // ADDED

但是请注意。这仅在唯一用法为 S<int> 时才有效。额外的扩展将需要额外的显式实例化条目。

您也可以通过直接专业化来做到这一点,例如将您的 .cpp 更改为只执行此操作:

#include "MyClass.h"
#include <iostream>

template <>
void S<int>::f()
{
    std::cout << "f()\n";
}

void MyClass::g()
{
    std::cout << "g()\n";
}

但这在我看来是相当有限的,因为您添加的每个额外类型都需要自己的专业化。

无论如何,祝你好运。

添加显式实例化

template
struct S<int>;

到"myclass.cpp"使代码编译。

松散地说,从 S<int> 推导的只是 "instantiates" class 定义,而不是成员。
编译器此时无法实例化 f,因为 f 的定义未知。

您需要为您使用的所有类型提供显式实例化,这在一定程度上限制了模板的实用性。

将模板定义保留在 headers 之外的一种流行方法是将它们放在自己的文件中,即 header.[=15 末尾的 #included =]