C++模板编程
781 浏览 5 years, 11 months
3.3 类模板的friend函数模板
版权声明: 转载请注明出处 http://www.codingsoho.com/类模板的friend函数模板
如果需要在类模板中重载运算符,函数模板会非常有用。例如,为了能把一个网格输出到一个流中,需要为Grid类模板重载插入运算符(operator<<) 。
根据前面的讨论,不能将operator<<设置为Grid类的成员:这个运算符必须是一个独立的函数模板。这个定义应该直接放在Grid.h中,如下所示:
template <typename T>
ostream& operator<<(ostream& ostr, const Grid<T>& grid)
{
for (size_t i = 0; i < grid.mHeight; i++) {
for (size_t j = 0; j < grid.mWidth; j++) {
// add a tab between each element of a row
ostr << grid.mCells[j][i] << "\t";
}
ostr << std::endl; // add a newline between each row
}
return ostr;
}
这个函数模板可用于任何Grid,只要网格的元素支持插入运算符即可。唯一存在的问题是operator<<访问了Grid类的protected成员。因此,operator<<必须是Grid类的friend。然而,Grid类和operator<<两者都是模板。实际上需要以下效果:operator<<对每一个特定类型T的实例化都是Grid模板对这个类型实例化的friend。这个语法如下所示:
// Forward declare Grid template.
template <typename T> class Grid;
// Prototype for templatized operator<<.
template<typename T>
ostream& operator<<(ostream& ostr, const Grid<T>& grid);
template <typename T>
class Grid
{
public:
friend ostream& operator<< <T>(ostream& ostr, const Grid<T>& grid);
};
friend声明比较棘手:这个语法表明,对于这个模板对类型T的实例,operator<<对类型T的实例是这个模板实例的friend。换句话说,类实例和函数实例之间存在一对一的friend映射关系。特别要注意operator<<中显式的模板规范<T>(<<后面的空格是可选的,但为了便于阅读,这里应该添加空格)。这个语法告诉编译器operator<<本身也是一个模板。