【问题标题】:How to handle ostream operator overloading inside templated class如何处理模板类中的ostream运算符重载
【发布时间】:2013-09-06 13:57:39
【问题描述】:

所以我有一个名为 list 的模板类

//List.h
#ifndef LIST_H
#define LIST_H
#include<fstream>

template <class T>
class List
{
    private:
        struct ListNode
        {
           T value;
           ListNode* next;
           ListNode* prev;

           ListNode(T value1, ListNode* next1 = NULL, ListNode* prev1 = NULL)
           {
            value = value1;
            next = next1;
            prev = prev1;
           }
        };
        ListNode* head;
        ListNode* tail;

   public:
       List() {head = NULL; tail = NULL;};
       ~List();
       void PrintForward(std::ostream &out);
       void PrintBackward(std::ostream &out);
       void InsertFront(const T &item);
       void InsertRear(const T &item);
       bool InsertAsNth(int N, const T &item);
       bool DeleteFront(T &val);
       bool DeleteRear(T &val);
       bool DeleteNth(int N, T &val);
       int DeleteAllOccur(const T &item);

       std::ostream& operator<< (std::ostream &out, List::ListNode const* p);

};
#endif

现在我一直在尝试编译它,但没有成功。我知道这与我让 ostream 运算符重载的方式有关,但不幸的是我真的不知道/找不到更好的方法。

这也是我的编译器错误

 warning C4346: 'List<T>::ListNode' : dependent name is not a type prefix with 'typename' to indicate a type

【问题讨论】:

  • @hetepeperfan 我也尝试了你所说的,但它工作了,虽然现在我有另一个有趣的编译器错误说二进制'运算符
  • 这是因为您已将其定义为采用三个参数:List(变为this)、std::ostreamList::ListNode。看我的回答。

标签: c++ class templates operator-overloading ostream


【解决方案1】:
std::ostream& operator<< (std::ostream &out, List::ListNode const* p);

必须成为

std::ostream& operator<< (std::ostream &out, typename List::ListNode const* p);

甚至可能

std::ostream& operator<< (std::ostream &out, typename List<T>::ListNode const* p);

更明确。

因为::ListNode 是模板类List 的依赖类型,C++ 编译器需要一点提示。在这种情况下,警告实际上非常有用,对于许多与模板相关的警告来说,这不能说是:)

【讨论】:

  • 哇,我不敢相信我错过了。非常抱歉浪费您的时间。
【解决方案2】:

编译器错误准确地说明了问题所在以及您必须做什么:List&lt;T&gt;::Node 是一个依赖于模板参数的限定 ID,因此编译器无法确定 Node 是一个类型还是一个值。所以你必须在它之前写typename来告诉编译器Node是一个类型。

我建议你检查这个问题:Where and why do I have to put the "template" and "typename" keywords?

【讨论】:

    【解决方案3】:

    您的代码至少存在两个主要问题。最多 关键是您要让operator&lt;&lt; 成为会员,并且 试图给它三个参数,这是完全非法的。 如果第一个参数是std::ostream&amp;,则没有 您可以将其定义为成员的方式;它必须是免费功能。 如果它还需要访问私人数据,那么您必须 让它成为朋友。但请注意:

    friend std::ostream& operator<<( std::ostream&, typename List::ListNode const* );
    

    使非模板函数成为朋友。不同的非模板 模板的每个实例化的函数。这很少见 想要什么。您可以进行特定的模板实例化 朋友,但前提是模板函数之前声明过 手。在这种情况下这是不可能的,因为其中一个 函数的参数具有嵌套类型。更地道的 解决这个问题的方法(无论如何,根据我的经验)是定义 好友内联:

    friend std::ostream& operator<<( std::ostream& dest, typename List::ListNode const& p )
    {
        //  ...
    }
    

    在这种情况下,operator&lt;&lt; 也是一个非模板函数,但是 定义嵌套在类模板中,所以你会得到 自动创建一个新的函数实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-19
      • 2017-10-29
      相关资源
      最近更新 更多