提问人:αλεχολυτ 提问时间:1/29/2015 更新时间:1/29/2015 访问量:1878
未定义对模板基类的成员函数的引用
Undefined reference to member function of template base class
问:
请考虑以下代码:
我的class.h:
template <class T>
struct S {
void f();
};
struct MyClass : public S<int>
{
void g();
};
我的类.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
}
我有链接器错误:
对“S::f()”的未定义引用
我可以在不将 S::f() 的实现转移到头文件的情况下解决这个问题吗? 为什么当我声明从完整的专用模板基类派生的 MyClass 时没有实例化 S::f()?
答:
如果不将 s::f() 函数的实现传输到头文件,就无法解决此问题。这是因为编译器在使用模板之前必须知道模板的实现。
为什么当我声明从完整的专用模板基类派生的 MyClass 时没有实例化 S::f()?
因为您的 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>
f
f
您需要为正在使用的所有类型提供显式实例化,这在一定程度上限制了模板的实用性。
将模板定义排除在标头之外的一种流行方法是将它们放在自己的文件中,该文件位于标头末尾的 d。#include
评论