使用friend
在类定义中定义全局函数被认为是一种好习惯,即使不需要访问私有成员也是如此。例如
template<typename T>
class A {
public:
A(T v);
T value() const;
friend A operator+(T n, const A& a) {
return A(a.value() + n);
}
};
而不是
template<typename T>
class A {
public:
A(T v);
T value() const;
};
template<typename T>
A<T> operator+(T n, const A<T>& a) {
return A<T>(a.value() + n);
}
即使operator+
仅使用公开的value()
。
这是常见的,我们不建议使用吗?
答案 0 :(得分:4)
这里friend
有一个主要优势。当我们定义:
friend A operator+(T, const A&);
这是不的功能模板。这只是一个功能 - 一个只能由ADL找到的特殊功能。但由于它不是功能模板,转换仍然可能发生。另一方面:
template <class T>
A<T> operator+(T, const A<T>&)
是一个普通的旧函数模板,其中包含有关模板类型推导的所有常规规则。
为什么这很重要?考虑:
A<double> a(4.2);
5 + a;
在第一种情况下,这非常好。我们发现operator+(double, const A<double>&)
,5
转换为5.0
,这是允许的转换,我们会返回A<double>(9.2)
。
在第二种情况下,模板推导失败,因为T
推导出两个参数的不同类型。因此,代码是不正确的。