【问题标题】:error when trying to overload << operator and using friend function尝试重载 << 运算符并使用友元函数时出错
【发布时间】:2015-01-11 04:27:36
【问题描述】:

我正在尝试重载 运算符并使用友元函数。 下面的代码块工作得很好。

template <class T>
class Mystack{
    friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
    {
        d.print(s);
        return s;
    } 
};

由于它是友元函数,我显然想在类之外定义它而不使用范围解析运算符。但是当我尝试时,我得到了错误。

template <class T>
class Mystack{
    friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d); 
};
template <class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
    d.print(s);
    return s;
}

下面是 main 的代码 sn-p

Mystack<int> intstack;
std::cout << intstack;

错误:未解析的外部符号。

P.S:它不是完整的运行代码。只是一个样本。请多多包涵。

【问题讨论】:

  • class sample{ 不应该是class Mystack
  • 涉及模板的时候,只要把所有的东西都放在头文件里。这不值得头疼。
  • @NeilKirk 我收到 OP 的错误,所有内容都在一个文件中 see here

标签: c++


【解决方案1】:
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);

声明一个非模板operator&lt;&lt; 函数并使其成为朋友。所以Mystack&lt;int&gt; 将有一个非模板函数std::ostream&amp; operator&lt;&lt;(std::ostream&amp; s, Mystack&lt;int&gt; const&amp; d); 等作为它的朋友。

template<class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
    d.print(s);
    return s;
}

定义一个operator&lt;&lt;函数模板。

两者不一样。当您编写 std::cout &lt;&lt; intstack; 时,重载解析规则将其解析为您声明的非模板 operator&lt;&lt; 函数,但它未定义,因此您会收到链接器错误。

没有办法为类模板之外的类模板的每个实例定义一个非模板函数。但是,您可以与 operator&lt;&lt; 函数模板的特化成为朋友:

// forward declarations
template <class T>
class Mystack;
template <class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);

template <class T>
class Mystack
{
    friend std::ostream& operator<< <T>(std::ostream& s, Mystack<T> const& d); 
//                                  ^^^
};

或与函数模板的每一个特化成为朋友,从封装的角度来看更糟糕(因为,例如,operator&lt;&lt; &lt;int&gt; 将成为 Mystack&lt;float&gt; 的朋友):

template <class T>
class Mystack
{
public:
    template <class U>
    friend std::ostream& operator<<(std::ostream& s, Mystack<U> const& d);
};

或者只是在类中定义友元函数。

【讨论】:

  • 如果我从函数中删除 template &lt;class T&gt; 会怎样。然后我也得到了错误。
  • @tanz 就像std::ostream&amp; operator&lt;&lt;(std::ostream&amp; s, Mystack&lt;T&gt; const&amp; d)?那你就不能用T了。
  • @T.C.你能详细说明哪种方式是最好的方式吗?我的意思是这种情况的最佳实践是什么(例如,为类模板添加运算符重载...)。我们应该使用类内定义还是您提到的第一种方式(第二种方式显然很危险)。
猜你喜欢
  • 1970-01-01
  • 2018-09-17
  • 2017-07-26
  • 1970-01-01
  • 2014-03-18
  • 2021-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多