我不知道为什么会发生这种情况,因为我认为我已经正确声明和定义了所有内容。
我有以下程序,是用模板设计的。
我已经在精细的"nodo_colaypila.h"中定义了队列的节点:
#ifndef NODO_COLAYPILA_H
#define NODO_COLAYPILA_H
#include <iostream>
template <class T> class cola;
template <class T> class nodo_colaypila
{
T elem;
nodo_colaypila<T>* sig;
friend class cola<T>;
public:
nodo_colaypila(T, nodo_colaypila<T>*);
};
然后在"nodo_colaypila.cpp"中实现
#include "nodo_colaypila.h"
#include <iostream>
template <class T> nodo_colaypila<T>::nodo_colaypila(T a, nodo_colaypila<T>* siguiente = NULL)
{
elem = a;
sig = siguiente;//ctor
}
接下来是队列模板类及其函数的定义和声明:
“可乐.h”:
#ifndef COLA_H
#define COLA_H
#include "nodo_colaypila.h"
template <class T> class cola
{
nodo_colaypila<T>* ult, pri;
public:
cola<T>();
void anade(T&);
T saca();
void print() const;
virtual ~cola();
};
#endif // COLA_H
“可乐.cpp”:
#include "cola.h"
#include "nodo_colaypila.h"
#include <iostream>
using namespace std;
template <class T> cola<T>::cola()
{
pri = NULL;
ult = NULL;//ctor
}
template <class T> void cola<T>::anade(T& valor)
{
nodo_colaypila <T> * nuevo;
if (ult)
{
nuevo = new nodo_colaypila<T> (valor);
ult->sig = nuevo;
ult = nuevo;
}
if (!pri)
{
pri = nuevo;
}
}
template <class T> T cola<T>::saca()
{
nodo_colaypila <T> * aux;
T valor;
aux = pri;
if (!aux)
{
return 0;
}
pri = aux->sig;
valor = aux->elem;
delete aux;
if(!pri)
{
ult = NULL;
}
return valor;
}
template <class T> cola<T>::~cola()
{
while(pri)
{
saca();
}//dtor
}
template <class T> void cola<T>::print() const
{
nodo_colaypila <T> * aux;
aux = pri;
while(aux)
{
cout << aux->elem << endl;
aux = aux->sig;
}
}
然后,我有一个程序来测试这些功能,如下所示:
“主.cpp”
#include <iostream>
#include "cola.h"
#include "nodo_colaypila.h"
using namespace std;
int main()
{
float a, b, c;
string d, e, f;
cola<float> flo;
cola<string> str;
a = 3.14;
b = 2.71;
c = 6.02;
flo.anade(a);
flo.anade(b);
flo.anade(c);
flo.print();
cout << endl;
d = "John";
e = "Mark";
f = "Matthew";
str.anade(d);
str.anade(e);
str.anade(f);
cout << endl;
c = flo.saca();
cout << "First In First Out Float: " << c << endl;
cout << endl;
f = str.saca();
cout << "First In First Out String: " << f << endl;
cout << endl;
flo.print();
cout << endl;
str.print();
cout << "Hello world!" << endl;
return 0;
}
但是当我构建时,编译器会在模板类的每个实例中抛出错误:
undefined reference to `cola(float)::cola()’…(它实际上是 cola’<‘float’>’::cola(),但这不允许我那样使用它。)
等等。
为什么是这样?
我在这里读到,出于某种原因,我应该将每个函数的声明放在头文件中。
答案
这是C编程中的一个常见问题。
模板中的代码仅仅是编译器已知的"模式"。cola<float>::cola(...)
和cola<string>::cola(...)
直到被迫这样做为止。至少 在整个编译过程中一次,否则我们会得到"未定义的引用"错误。 cola<T>
还。)
了解问题
问题是由以下事实引起的:main.cpp
和cola.cpp
会先单独编译。main.cpp
,编译器将隐含地 实例化模板类cola<float>
和cola<string>
因为这些特定的实例化用于main.cpp
。main.cpp
,也不包含在任何头文件中main.cpp
,因此编译器不能在中包含这些函数的完整版本main.o
。cola.cpp
,编译器也不会编译这些实例化,因为没有隐式或显式实例化cola<float>
或者cola<string>
。cola.cpp
,编译器不知道需要哪些实例化;每一个 键入以确保此问题永远不会发生! cola<int>
,cola<char>
,cola<ostream>
,cola< cola<int> >
… 等等 …)
这两个答案是:
- 告诉编译器,在最后
cola.cpp
,需要哪些特定的模板类,强制其编译cola<float>
和cola<string>
。 - 将成员函数的实现放在将要包含的头文件中每一个 为任何其他"翻译单元"计时(例如
main.cpp
) 使用模板类。
答案 1:显式实例化模板及其成员定义
在结尾 的cola.cpp
,您应该添加显式实例化所有相关模板的行,例如
template class cola<float>;
template class cola<string>;
然后在末尾添加以下两行nodo_colaypila.cpp
:
template class nodo_colaypila<float>;
template class nodo_colaypila<std :: string>;
这将确保,当编译器编译时cola.cpp
它将显式编译所有代码cola<float>
和cola<string>
类。nodo_colaypila.cpp
包含的实现nodo_colaypila<...>
类。
在这种方法中,您应该确保所有的实现都被放入一个.cpp
文件(即一个翻译单元),并且显式实例化放置在所有函数的定义之后(即文件末尾)。
答案2:将代码复制到相关头文件中
常见的答案是从实现文件中移走所有代码cola.cpp
和nodo_colaypila.cpp
进入cola.h
和nodo_colaypila.h
。cola<char>
)无需任何更多工作。
概括
例如,STL 使用的默认答案以及我们任何人将编写的大多数代码中使用的默认答案是将所有实现放在头文件中。cola<float>
和cola<string>
,如果您想使用其他东西,请先告诉我,我们可以在启用它之前验证它是否有效。")。
最后,您问题中的代码中还有其他三个小拼写错误:
- 您缺少一个
#endif
在 nodo_colaypila.h 的末尾 - 在 cola.h 中
nodo_colaypila<T>* ult, pri;
应该nodo_colaypila<T> *ult, *pri;
- 两者都是指针。 - nodo_colaypila.cpp:默认参数应该在头文件中
nodo_colaypila.h
,不在这个实现文件中。