我重载了'<<<链接类实现中的运算符,我在我的main函数中声明了.cpp文件,但是它不起作用,并且发生以下错误: 运算符的未定义引用<&列表)
这是linkedlist.h文件中ostream函数的声明:
friend std::ostream& operator<< (std::ostream& os, LinkedList<T>& list);
这是ostream函数的实现:
template <typename T>
std::ostream& operator<< (std::ostream& os, LinkedList<T> list)
{
list.current = list.start;
while(list.current != NULL)
{
os<< list.current->info<<" -> ";
list.current = list.current->next;
}
os<<"NULL"<<endl;
return os;
}
在main函数中,我创建了一个包含SavingAccount类
对象的列表LinkedList <SavingAccount> list;
并且错误发生在此行的main函数中:
cout << list <<endl;
嗯..这是LinkedList类的实现:
#include "LinkedList.h"
#include "SavingAccount.h"
#include <cstddef>
using namespace std;
template <typename T>
LinkedList<T>::LinkedList()
{
start = NULL;
current = NULL;
}
template <typename T>
LinkedList<T>::~LinkedList()
{
// Add code.
}
template <typename T>
std::ostream& operator<< (std::ostream& os,const LinkedList<T>& list) {
list.current = list.start;
while(list.current != NULL)
{
os<< list.current->info<<" -> ";
list.current = list.current->next;
}
os<<"NULL"<<endl;
return os;
}
这是LinkedLins类的头文件:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include<iostream>
using namespace std;
template <typename T>
struct Node{
T info;
Node<T> *next;
};
template <typename T>
class LinkedList
{
Node<T> *start;
Node<T> *current;
public:
LinkedList();
~LinkedList();
friend std::ostream& operator<< (std::ostream& os, const LinkedList<T>& list);
};
#endif // LINKEDLIST_H
我希望你们可以帮助我,非常感谢你的帮助
答案 0 :(得分:1)
我不确定这是否是导致错误的原因,但您的函数定义与函数声明不同:
// you left out a & (reference sign) - LinkedList<T>& list in declaration
std::ostream& operator<< (std::ostream& os, LinkedList<T> list)
Petr Budnik 是对的,您需要将模板实施保存在与定义相同的文件中。
有一件事他没有提到(这可能会导致你出现问题):你需要明确表示你使用template T
超过<<
重载:
template < typename T>
friend std::ostream& operator<< (std::ostream& os, LinkedList<T>& list);
另外,如果您打算修改传入的const
,请删除LinkedList
。
这是(大致)你的LinkedList.h
应该是什么样的:
template <typename T>
struct Node{
T info;
Node<T> *next;
};
template <typename T>
class LinkedList
{
Node<T> *start;
Node<T> *current;
public:
LinkedList();
~LinkedList();
template < typename T>
friend std::ostream& operator<< (std::ostream& os, LinkedList<T>& list);
};
template <typename T>
LinkedList<T>::LinkedList()
{
start = NULL;
current = NULL;
}
template <typename T>
LinkedList<T>::~LinkedList()
{
// Add code.
}
template <typename T>
std::ostream& operator<<(std::ostream& os, LinkedList<T>& list) {
list.current = list.start;
while (list.current != NULL)
{
os << list.current->info << " -> ";
list.current = list.current->next;
}
os << "NULL" << endl;
return os;
}
P.S。
我建议您使用nullptr
代替0
或NULL
吗?它是一种新的C ++ 11语法,并且有一些好处(如果需要,请阅读它)。
希望这有帮助!
答案 1 :(得分:1)
好的,在您发布代码后,您的问题似乎是您在标头和源文件之间拆分LinkedList
模板声明和实现。除非您在源文件中进行显式实例化,否则您无法执行此操作:您无法将模板声明和实现分开,它们必须位于一个标头中。
您需要将 LinkedList.cpp 的内容放在 LinkedList.h 中,完全删除源文件,并在需要的地方添加更新的标题它
P.S。另外,一般来说,通过const
引用修改对象并不是一个好主意。编译器不会喜欢它。您可能想重新考虑您的设计。
P.P.S。如果您真的想要并且意味着修改您通过const
引用访问的类的对象中的某些数据成员,则需要将这些数据成员声明为mutable
。
P.P.P.S。详细说明模板foo
类的模板函数bar
朋友声明,避免在评论中进行冗长的讨论。
如果你在类中定义了这样的函数及其声明,那么这是一个简单的事情 - 只需使用friend
关键字。例如,friend void foo( bar< T > & ) { ... }
。
如果在类之外单独定义它,则需要在声明中使用略有不同的语法,并避免模板参数的隐藏:template< typename U > friend void foo( bar< U > & ) { ... }
(假设U
未在{{{}中的模板参数中使用1}}类声明)。然后你在课外定义它。
如果要为bar
指定默认模板参数,则会变得更加棘手。您不能在foo
声明中使用默认模板参数,因此您必须转发声明所有内容:
friend
最后一个P.P.P.P.S(我希望!)。由于您在template< typename T > class bar;
template< typename T = int >
void foo( bar< T > & );
template< typename T >
class bar
{
template< typename U >
friend void foo( bar< U > & );
};
template< typename T >
void foo( bar< T > & )
{
...
}
operator <<
中使用SavingAccount
类型operator <<
,因此您还需要为LinkedList
定义operator <<
。
请自行注意:请勿在评论部分回答其他答案中的问题;)。
答案 2 :(得分:0)
除了非常病态的情况,“ouptut”操作不应该改变要输出的值,所以适当的函数原型应该
template<class T>
std::ostream& operator<<(std::ostream& s, const LinkedList<T>& list)
{
...
}
并且您不应将新值分配给list
成员(例如list.current = list.start
)。
你最好重新考虑逻辑......
此外,模板功能必须在头文件中实现,而不是cpp文件