文章目录
- 条款 24:若所有参数皆需类型转换,请为此采用 non-member 函数
- 核心思想
- 示例代码
- 说明
- 结论
条款 24:若所有参数皆需类型转换,请为此采用 non-member 函数
核心思想
-
成员函数的限制
- 成员函数的第一个参数(隐式
this
指针)绑定到调用对象,不能对它进行类型转换。
- 成员函数的第一个参数(隐式
-
non-member 函数的优势
- 非成员函数可以对所有参数进行类型转换,因为它们的所有参数都是显式的。
-
设计原则
- 当函数需要对包括调用对象在内的所有参数进行类型转换时,应设计为 non-member 函数。
示例代码
#include <iostream>class Rational { public:Rational(int numerator = 0, int denominator = 1): n(numerator), d(denominator) {}int numerator() const { return n; }int denominator() const { return d; }private:int n; // 分子int d; // 分母 };// non-member 函数,实现两数相乘 Rational operator*(const Rational& lhs, const Rational& rhs) {return Rational(lhs.numerator() * rhs.numerator(),lhs.denominator() * rhs.denominator()); }int main() {Rational r1(1, 2);Rational r2(2, 3);Rational result = r1 * r2; // 合法,调用 non-member 函数result = r1 * 2; // 合法,对第二个参数进行类型转换result = 3 * r2; // 合法,对第一个参数进行类型转换std::cout << "Result: " << result.numerator() << "/" << result.denominator() << std::endl;return 0; }
说明
-
为什么使用 non-member 函数?
- 如果
operator*
被定义为成员函数,则调用r1 * 2
和3 * r2
都会失败:r1 * 2
:右侧的整数2
无法隐式转换为Rational
类型。3 * r2
:左侧的整数3
无法隐式转换为Rational
类型。
- 定义为非成员函数后,编译器可以通过构造函数将
2
和3
转换为Rational
类型,支持上述用法。
- 如果
-
成员函数的限制
- 成员函数只能为显式参数(非隐式的
this
指针)提供类型转换。
Rational operator*(const Rational& rhs); // 如果是成员函数 // r1 * 2 合法,但 3 * r2 无法编译,因为调用对象 3 无法转换为 Rational 类型。
- 成员函数只能为显式参数(非隐式的
-
non-member 函数的灵活性
- non-member 函数的所有参数都是显式的,编译器可自由对它们进行类型转换,支持更广泛的操作形式。
结论
- 若所有参数(包括隐式的调用对象)都需要类型转换,应使用 non-member 函数。
- non-member 函数为类型转换提供了更多的灵活性,避免了成员函数的类型限制。
- 使用
non-member
函数时,仍可将其放入与类相关的命名空间中,以保持逻辑清晰。