2.4 Friends
2.4 友元
Instead of printing the stack contents with printOn() it is better to implement toperator<< for the stack. However, as usual operator<< has to be implemented as nonmember function, which then could call printOn() inline:
与其使用printOn()打印栈内容,不如为栈实现operator<<运算符。但是,通常oeraptor<<必须实现为非成员函数,然后以内联方式调用printOn()。
template<typename T>
class Stack {
…
void printOn() (std::ostream& strm) const {
…
}
friend std::ostream& operator<< (std::ostream& strm, Stack<T> const& s) {
s.printOn(strm);
return strm;
}
};
Note that this means that operator<< for class Stack<> is not a function template, but an “ordinary” function instantiated with the class template if needed.
注意,这意味着对于Stack<>类的operator<<不是函数模板,而是在需要时根据类模板实例化出来的一个“普通”函数。
However, when trying to declare the friend function and define it afterwards, things become more complicated. In fact, we have two options:
但是,当尝试声明友元函数并在之后定义它时,事情变成更加复杂。实际上,我们有两个选择:
1. We can implicitly declare a new function template, which must use a different template parameter, such as U:
1. 我们可以隐式声明一个新的函数模板,该模板必须使用不同的模板参数(如U):
template<typename T>
class Stack {
…
template<typename U>
friend std::ostream& operator<< (std::ostream&, Stack<U> const&);
};
Neither using T again nor skipping the template parameter declaration would work (either the inner T hides the outer T or we declare a nontemplate function in namespace scope).
再次使用T或不声明模板参数都将不起作用(要么是因为内部T隐藏了外部T,要么是在命名空间作用域内声明非模板函数)
2. We can forward declare the output operator for a Stack<T> to be a template, which, however, means that we first have to forward declare Stack<T>:
我们可以Stack<T>的operator<<运算符声明为模板,但这意味着我们必须先声明Stack<T>:
template<typename T> class Stack;
template<typename T>
std::ostream& operator<< (std::ostream&, Stack<T> const&);
Then, we can declare this function as friend:
然后,我们可以将此函数声明为友元:
template<typename T>
class Stack {
…
friend std::ostream& operator<< <T> (std::ostream&, Stack<T> const&);
};
Note the <T> behind the “function name” operator<<. Thus, we declare a specialization of the nonmember function template as friend. Without <T> we would declare a new nontemplate function. See Section 12.5.2 on page 211 for details.
注意,<T>在“函数名称”operator<<的后面。因此,我们将一个特殊的非成员模板函数声明为友元。如果没有<T>,我们声明的是一个新的非模板函数。详见第211页的12.5.2节。
In any case, you can still use this class for elements that don’t have operator<< defined. Only calling operator<< for this stack results in an error:
任何时候,你都可以将此类用于未定义operator<<的元素。仅当该栈调用operator<<时才会出现错误:
Stack<std::pair< int, int>> ps; // std::pair<> 没有定义operator<<
ps.push({4, 5}); // OK
ps.push({6, 7}); // OK
std::cout << ps.top().first << ’\n’; // OK
std::cout << ps.top().second << ’\n’; // OK
std::cout << ps << ’\n’; //错误: 元素类型不支持operator<< 操作
来源:oschina
链接:https://my.oschina.net/u/4286379/blog/3236042