【问题标题】:i have done the <<operator overloading but it's not working我已经完成了 << 运算符重载,但它不起作用
【发布时间】:2013-08-18 20:52:46
【问题描述】:

我在链接类实现中重载了'对运算符的未定义引用

这是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;
 }

在主函数中,我创建了一个包含来自 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

希望大家能帮帮我,非常感谢您的帮助

【问题讨论】:

  • 你是在头文件中实现的吗?
  • 比较你的声明和你的定义(第二个参数)。
  • 为什么要将current 节点保留在实际的列表类中?
  • 另外,如果您询问有关编译器/链接器错误的问题,您也可以通过在问题中发布实际错误来提供帮助。请尽可能完整且未经编辑。
  • @Oleksiy 模板不是这样。

标签: c++ data-structures linked-list operator-overloading code-separation


【解决方案1】:

好的,在您发布代码之后,您的问题似乎是您在头文件和源文件之间拆分了LinkedList 模板声明和实现。除非您在源文件中进行显式实例化,否则您不能这样做:您不能将模板声明和实现分开,它们必须在一个标头中。

您需要将 LinkedList.cpp 的内容放在 LinkedList.h 中,完全摆脱源文件,只需在需要的地方包含更新的标题它。

附:此外,一般来说,通过const 引用修改对象并不是一个好主意。编译器不会喜欢它。您可能需要重新考虑您的设计。

附言如果您真的想要并且打算修改通过const 引用访问的类的对象中的某些数据成员,则需要将这些数据成员声明为mutable

P.P.P.S.详细说明模板函数foo 模板bar 类的朋友声明,避免在cmets 中进行冗长的讨论。

如果您在类中定义此类函数及其声明,这是一件简单的事情 - 只需使用 friend 关键字。例如,friend void foo( bar&lt; T &gt; &amp; ) { ... }

如果你在类外单独定义,你需要在声明中使用稍微不同的语法,避免模板参数的阴影:template&lt; typename U &gt; friend void foo( bar&lt; U &gt; &amp; ) { ... }(假设Ubar类声明的模板参数中没有使用) .然后你在类之外定义它。

如果您想为foo 指定默认模板参数,它会变得更加棘手。您不能在 friend 声明中使用默认模板参数,因此您必须转发声明所有内容:

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 > & )
{
 ...
}

最后一个 P.P.P.P.S(我希望!)。由于您在operator &lt;&lt; 中为LinkedList 使用operator &lt;&lt; 类型SavingAccount,因此您也需要为SavingAccount 定义operator &lt;&lt;

自我说明:不要将 cmets 部分的问题回答为另一个答案;)。

【讨论】:

  • 我已将内容拉到我的头文件并更新了所有内容,并且我已经取消了 const。现在我面临一个错误:'std::ostream& LinkedListstd::operator& list) 必须只采用一个参数'
【解决方案2】:

我不确定这是否是导致错误的原因,但您的函数定义与您的函数声明不同:

// you left out a & (reference sign) - LinkedList<T>& list in declaration
std::ostream& operator<< (std::ostream& os, LinkedList<T> list) 

编辑

Petr Budnik 是对的,您需要将模板实现与您的定义保存在同一个文件中。

有一件事他没有提到(这可能会给你带来问题):你需要明确表明你在&lt;&lt; 重载之上使用了template T

template < typename T>
friend std::ostream& operator<< (std::ostream& os, LinkedList<T>& list);

另外,如果您打算修改您传入的LinkedList,请删除const

这是您的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;
}    

附言

我可以建议您使用nullptr 而不是0NULL 吗?它是一种新的 C++11 语法,有一些好处(如果需要,请阅读它)。

希望这会有所帮助!

【讨论】:

  • @Alladinsaoudi 你能贴出你的 LinkedList 类的代码吗?
  • 我已经编辑了问题,你可以在那里看到代码。谢谢你^^
  • @Alladinsaoudi,你能在你的头文件中发布LinkedList的声明吗?
  • 有什么想法吗?因为我被卡住了,如果我不解决这个问题,我将无法继续
  • 我已经完成了你所说的一切,但是添加“template ”会导致再次声明模板的问题,出现此错误:声明'class T'并且当我删除它时行,第一个错误再次发生(未定义引用
【解决方案3】:

除了非常病态的情况外,“输出”操作不应该改变要输出的值,所以正确的函数原型应该是

template<class T>
std::ostream& operator<<(std::ostream& s, const LinkedList<T>& list)
{
...
}

并且您不应该为list 成员分配新值(例如在list.current = list.start 中)。 你最好也重新考虑一下逻辑......

另外,模板功能必须在头文件中实现,而不是在 cpp 文件中

【讨论】:

    猜你喜欢
    • 2023-04-05
    • 1970-01-01
    • 2023-01-19
    • 2015-05-05
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    • 2020-01-16
    • 1970-01-01
    相关资源
    最近更新 更多