template class Rational { public: ... friend const Rational operator*(const Rational& lhs, const Rational& rhs); ... }; |
然而,使用缩写形式更简单(而且更常用)。
现在返回到连接问题。混合模式代码编译,因为编译器知道我们想要调用一个特定的函数(取得一个 Rational 和一个 Rational 的 operator*),但是那个函数只是在 Rational 内部声明,而没有在此处定义。我们的意图是让 class 之外的 operator* template(模板)提供这个定义,但是这种方法不能工作。如果我们自己声明一个函数(这就是我们在 Rational template(模板)内部所做的事),我们就有责任定义这个函数。当前情况是,我们没有提供定义,这也就是连接器为什么不能找到它。
让它能工作的最简单的方法或许就是将 operator* 的本体合并到它的 declaration(定义)中:
template class Rational { public: ...
friend const Rational operator*(const Rational& lhs, const Rational& rhs) { return Rational(lhs.numerator() * rhs.numerator(), // same impl lhs.denominator() * rhs.denominator()); // as in } //《C++箴言:声明为非成员函数的时机》 }; |
确实,这样就可以符合预期地工作:对 operator* 的混合模式调用现在可以编译,连接,并运行。万岁!
关于此技术的一个有趣的观察结论是 friendship 的使用对于访问 class 的 non-public parts(非公有构件)的需求并没有起到什么作用。为了让所有 arguments(实参)的 type conversions(类型转换)成为可能,我们需要一个 non-member function(非成员函数)(《C++箴言:声明为非成员函数的时机》 依然适用);而为了能自动实例化出适当的函数,我们需要在 class 内部声明这个函数。在一个 class 内部声明一个 non-member function(非成员函数)的唯一方法就是把它做成一个 friend(友元)。那么这就是我们做的。反传统吗?是的。有效吗?毫无疑问。
<<上一页
1
2
3
4
下一页>>
|