另一个类中嵌套模板的外部实例化



我必须用class SmartPointer对int指针列表进行排序。但是在class ListeTriee类型的对象liste2所在的开头在main.cpp中实例化我收到一条错误消息:

来自编译器的错误消息

Undefined symbols for architecture x86_64:
"ListeTriee<SmartPointer<int> >::ListeTriee()", referenced from:
_main in main.cpp.o
"ListeTriee<SmartPointer<int> >::~ListeTriee()", referenced from:
_main in main.cpp.o
ld: symbol(s) not found for architecture x86_64

我认为在ListeTriee.cpp.中用给定的模板参数实例化模板时会出现问题

MacBook Pro,CLion 2016.3.2

Main.cpp

int main()
{
cout << "*** 7. Liste triee de pointeurs de int AVEC SmartPointer ***************************************************" << endl;
ListeTriee<SmartPointer<int> > liste2;
/*
liste2.insere(new int (5));   // ne pas oublier de redefinir operator= de SmartPointer !!!
liste2.insere(new int (2));
liste2.insere(new int (8));
liste2.insere(new int (3));
liste2.Affiche(); // redefinir operator<< de SmartPointer de telle sorte qu'il affiche la valeur du pointeur
return 0;
}

导致问题的线路如下:ListeTriee<SmartPointer<int> > liste2;

SmartPointer.h

#ifndef C_PROGRAMM8_SMARTPOINTER_H
#define C_PROGRAMM8_SMARTPOINTER_H
#include <iostream>
#include <stdlib.h>
#include "Ligne.h"
using namespace std;
template <class T> class SmartPointer{
private:
T *val;
public:
//Constructeurs
SmartPointer<T>();
SmartPointer<T>(SmartPointer<T> *);
SmartPointer<T>(T *);
//Destructeur
~SmartPointer<T>();
//Surcharge d'opérateurs
bool operator <(const SmartPointer &) const;                  //<
friend ostream &operator<<(ostream &, SmartPointer<T> *);
T* operator->() const;
T& operator*() const;
//Getter
T* getVal() const;
//Autre
void Delete();
};
#endif //C_PROGRAMM8_SMARTPOINTER_H

SmartPointer.cpp

#include "SmartPointer.h"
template <class T>
SmartPointer<T>::SmartPointer() {
cout << "-> Constructeur par defaut [SmartPointer]" << endl;
val = NULL;
}
template <class T>
SmartPointer<T>::SmartPointer(T *new_Val) {
cout << "-> Constructeur d initialisation [SmartPointer]" << endl;
val = new_Val;
}
template <class T>
SmartPointer<T>::SmartPointer(SmartPointer<T> *new_SmartPointer) {
cout << "-> Constructeur de copie [SmartPointer]" << endl;
*val = *(new_SmartPointer -> val);
}
template <class T>
SmartPointer<T>::~SmartPointer() {
cout << "-> Destructeur [SmartPointer]" << endl;
}
template <class T>
bool SmartPointer<T>::operator<(const SmartPointer &new_SmartPointer) const {
if(*val < *(new_SmartPointer.val))
return true;
else
return false;
}
template <class T>
T& SmartPointer<T>::operator*() const {
return *val;
}
template <class T>
T* SmartPointer<T>::operator->() const {
return val;
}
template <class T>
void SmartPointer<T>::Delete() {
cout << "-> Appel a 'Delete' de l objet pointee" << endl;
if(val != NULL)
delete val;
}
template <class T>
T *SmartPointer<T>::getVal() const {
return val;
}
template <class T>
ostream &operator<<(ostream &new_Out, SmartPointer<T> *new_SmartPointer){
new_Out << new_SmartPointer;
return new_Out;
}
template class SmartPointer<int>;
template class SmartPointer<Ligne>;

ListeTrie.h

#ifndef C_PROGRAMM6_LISTETRIEE_H
#define C_PROGRAMM6_LISTETRIEE_H
#include "ListeBase.h"
template <class T>
class ListeTriee : public ListeBase<T>{
public:
//Constructeurs
ListeTriee();
ListeTriee(const ListeTriee &);
//Destructeurs
virtual ~ListeTriee();
//Methodes virtual
virtual T *insere(const T &);
};
#endif //C_PROGRAMM6_LISTETRIEE_H

ListeTrie.cpp

#include "ListeTriee.h"
template <class T>
ListeTriee<T>::ListeTriee() : ListeBase<T>(){
cout << "-> Constructeur par defaut [ListeTriee]" << endl;
}
template <class T>
ListeTriee<T>::ListeTriee(const ListeTriee & new_ListeTriee) : ListeBase<T>(new_ListeTriee){
cout << "-> Constructeur de copie [ListeTriee]" << endl;
}
template <class T>
ListeTriee<T>::~ListeTriee() {
cout << "Destructeur [ListeTriee]" << endl;
}
template <class T>
T* ListeTriee<T>::insere(const T &new_T) {
Cellule<T> *TmpPrec, *Tmp, *Ajout;
Ajout = new Cellule<T>;
Ajout -> valeur = new_T;
Ajout -> suivant = NULL;
if(this -> ptete == NULL) {
this->ptete = Ajout;
}
else{
TmpPrec = NULL;
Tmp = this -> ptete;
while(Tmp -> suivant != NULL && Ajout -> valeur > Tmp -> valeur){
TmpPrec = Tmp;
Tmp = Tmp -> suivant;
}
if(Ajout -> valeur <= Tmp -> valeur)
{
//Nouvelle valeur va être placée au début de la liste
if(TmpPrec == NULL)
{
Ajout -> suivant = this -> ptete;
this -> ptete = Ajout;
}
else{   //Val se trouve entre la position 1 et n - 1
TmpPrec -> suivant = Ajout;
Ajout -> suivant = Tmp;
}
}
else
{   //Élément se trouve à la fin de la liste
Tmp -> suivant = Ajout;
Ajout -> suivant = NULL;
}
}
//cout << Ajout -> valeur << endl;
return &Ajout -> valeur;
}
template class ListeTriee<int*>;
template class ListeTriee<int>;
template class Cellule<int>;
template class ListeTriee<Couleur>;

我已经尝试了显式实例化:在ListeTree.cpp的末尾使用template class ListeTriee<SmartPointer<int> >;,这样编译器就可以使用给定的模板参数创建一个新的类,但我得到的错误消息甚至更大。

您需要将显式实例化放入头文件中,这样编译器就会知道某个翻译单元中存在模板体,并且不会抱怨无法将模板体放入当前翻译单元。请注意,您将需要所有模板类的显式实例化,也就是SmartPointer<int>

根据msdn源代码组织(C++模板(,模板与普通类不同,因为编译器不会为模板或其任何成员生成对象代码。在使用具体类型实例化模板之前,不需要生成任何内容。当编译器遇到诸如MyClass mc;之类的模板实例化时;,并且还不存在具有该签名的类,则它生成一个新的类。它还尝试为所使用的任何成员函数生成代码。如果这些定义在一个文件中,而该文件没有直接或间接包含在正在编译的.cpp文件中,则编译器将看不到它们。从编译器的角度来看,这不一定是错误,因为函数可能在另一个翻译单元中定义,在这种情况下,链接器会找到它们。如果链接器找不到该代码,则会引发未解析的外部错误。

最新更新