错误:E:\Qt Project\test02\main.cpp:3048: error: undefined reference to `listsavitch::operator<<(std::ostream&, listsavitch::GenericList<int> const&)”
E:\Qt Project\test02\main.cpp:3055: error: undefined reference to `listsavitch::operator<<(std::ostream&, listsavitch::GenericList<char> const&)”
这种错误该怎么解决呢?友元函数是不能定义模板吗?还有一个警告,说是在头文件定义的不是一个模板函数。
E:\Qt Project\test02\main.cpp:3055: error: undefined reference to `listsavitch::operator<<(std::ostream&, listsavitch::GenericList<char> const&)”
这种错误该怎么解决呢?友元函数是不能定义模板吗?还有一个警告,说是在头文件定义的不是一个模板函数。
//接口文件 genericlist.h
#ifndef GENERICLIST_H
#define GENERICLIST_H
#include <iostream>
using namespace std;
namespace listsavitch
{
template <class ItemType>
class GenericList
{
public:
GenericList(int max);
~GenericList();
int length() const;
bool full() const;
void add(ItemType new_item);
void erase();
friend ostream& operator<<(ostream& outs, const GenericList<ItemType>& the_list); //问题出现在这里
private:
ItemType *item;
int max_length;
int current_length;
};
} //end listsavitch
#endif // GENERICLIST_H
#ifndef GENERICLIST_CPP
#define GENERICLIST_CPP
//实现文件 genericlist.cpp
#include <iostream>
#include <cstdlib>
#include "genericlist.h"
using namespace std;
namespace listsavitch
{
template <class ItemType>
GenericList<ItemType>::GenericList(int max)
:max_length(max), current_length(0)
{
item = new ItemType[max];
}
template <class ItemType>
GenericList<ItemType>::~GenericList()
{
delete [] item;
}
template <class ItemType>
int GenericList<ItemType>:: length() const
{
return current_length;
}
template <class ItemType>
bool GenericList<ItemType>:: full() const
{
return (max_length == current_length);
}
template <class ItemType>
void GenericList<ItemType>:: add(ItemType new_item)
{
if(full())
{
cout << "Error: Adding to a full list.\n";
exit(1);
}
else
{
item[current_length] = new_item;
current_length++;
}
}
template <class ItemType>
void GenericList<ItemType>:: erase()
{
current_length = 0;
}
template <class ItemType>
ostream& operator <<(ostream& outs,const GenericList<ItemType>& the_list) //问题出现在这里
{
for (int i = 0; i < the_list.current_length; i++)
outs << the_list.item[i] << endl;
return outs;
}
}
#endif //GENERICLIST_CPP
//应用程序 main.cpp
#include <iostream>
#include "genericlist.h"
#include "genericlist.cpp"
using namespace std;
using namespace listsavitch;
int main ()
{
GenericList<int> first_list(2);
first_list.add(3);
first_list.add(4);
cout << "first_list = \n";
cout << first_list ; //问题出现在这里,重载了操作符<<,但是没办法定义函数GenericList<int> & the_list
GenericList<char> second_list(10);
second_list.add("a");
second_list.add("b");
second_list.add("c");
cout << "second_list = \n";
cout << second_list;
return 0;
}
解决方案
5
解决办法:
genericlist.h中修改如下:
friend ostream& operator<< <ItemType>(ostream& outs, const GenericList<ItemType>& the_list);
模板是两次编译生成的,第一次生成的函数头和第二次生成的函数头不一样则报错。
只有在重载<<, >> 时,才使用友元函数,其他情况友元+模板,很复杂,禁止滥用友元函数。
genericlist.h中修改如下:
friend ostream& operator<< <ItemType>(ostream& outs, const GenericList<ItemType>& the_list);
模板是两次编译生成的,第一次生成的函数头和第二次生成的函数头不一样则报错。
只有在重载<<, >> 时,才使用友元函数,其他情况友元+模板,很复杂,禁止滥用友元函数。
10
本人记得有三个办法
1)不在外部定义友元函数,友元函数定义在 类的内部,原因是友元是类的接口。
这种方式最简洁。
1)不在外部定义友元函数,友元函数定义在 类的内部,原因是友元是类的接口。
这种方式最简洁。
template <typename ItemType>
class GenericList{
friend ostream& operator<<(ostream& outs, const GenericList& the_list){
// ....
return os;
};
};
2)类模板内部,声明友元模板函数,类外定义
这样唯一的缺陷是,全部友元模板函数,都是每个模板类的友元函数。
形成多对多友元,而不是一对一友元,
应用上没问题,逻辑上有问题
代码也比较简单,不如第一种方法简洁
template <typename T>
class GenericList{
//友元声明为模板函数
template <U>
friend ostream& operator<<(ostream& outs, const GenericList<U>& the_list);
};
template < ItemType>
friend ostream& operator<<(ostream& outs, const GenericList< ItemType>& the_list){
// ....
return os;
};
3)类内声明友元,类外实现,
需要 类模板GenericList 和operator<< 都前置声明
代码最复杂,不过满足了两个要求
3.1)类定义,和实现代码分离//仅仅是代码分离,不能分离编译
3.2)友元函数和模板类,是一对一关系,一个友元函数,对应一个模板类,逻辑正确。
// a)模板类类前置声明:
template <typename ItemType> class GenericList;
//b)模板函数 operator<< 前置声明 :
template <typename U>
ostream& operator<< (ostream& outs, const GenericList<U>& the_list);
//类定义
template <typename ItemType>
class GenericList
{
public:
/// 。
//c) 友元函数是模板函数的特化,在模板类中,这么写:
//注意 friend ostream& operator<< <>
//(ostream& outs,
//const GenericList& the_list); 注意GenericList&
friend ostream& operator<< <>(ostream& outs, const GenericList& the_list);
};
//类的实现部分:可分离编写
//d) 友元函数实现代码
template <class ItemType>
ostream& operator <<(ostream& outs,const GenericList<ItemType>& the_list) //没问题
{
for (int i = 0; i < the_list.current_length; i++)
outs << the_list.item[i] << endl;
return outs;
}
5
你非要这样写,那就点开本人给的链接,里面写的很清楚,关于产生这种问题的原因和解决方案。
本人的意思是,既然不能分开编译,那么写的时候干脆合并在一起就好了,就像那个链接最后那段代码一样,反而会方便一些。