> For the complete documentation index, see [llms.txt](https://jerakrs.gitbook.io/effective_c/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jerakrs.gitbook.io/effective_c/chapter4/section24.md).

# 条款24：若所有参数皆需类型转换，请为此采用 non-member 函数

Declare non-member functions when type conversions should apply to all parameters.

令 classes 支持隐式类型转换通常是个糟糕的行为，但也是有例外的，最常见的例外就是在建立数值类型的时侯。

考虑一个有理数类，允许整数隐式转换为有理数似乎很有道理：

```cpp
class Rational {
public:
    Rational(int numerator = 0, int denominator = 1);
    ...
};
```

现在研究一下这个类的乘法实现：

```cpp
class Rational {
public:
    const Rational operator* (const Rational& rhs) const;
};

Rational result, oneHalf;
// 尝试混合运算
result = oneHalf * 2;    // 成功；
result = 2 * oneHalf;    // 失败；
```

第一行的运算之所以成功是因为发生了隐式类型转换（implicit type conversion），编译器会自动调用 Rational 的构造函数将 int 变成 Rational。当然，只有在构造函数为 non-explicit 时，编译器才会这样做。所以为了实现混合运算，应该让 `operator*` 成为一个 non-member 函数：

```cpp
const Rational operator*(const Rational& lhs, const Rational& rhs) {
    return Rational(lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator());
}
```
