Effective C++ 条款24:若所有参数皆需类型转换,请为此采用 non-member 函数

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


核心思想

  1. 成员函数的限制

    • 成员函数的第一个参数(隐式 this 指针)绑定到调用对象,不能对它进行类型转换。
  2. non-member 函数的优势

    • 非成员函数可以对所有参数进行类型转换,因为它们的所有参数都是显式的。
  3. 设计原则

    • 当函数需要对包括调用对象在内的所有参数进行类型转换时,应设计为 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;
}

说明

  1. 为什么使用 non-member 函数?

    • 如果 operator* 被定义为成员函数,则调用 r1 * 23 * r2 都会失败:
      • r1 * 2:右侧的整数 2 无法隐式转换为 Rational 类型。
      • 3 * r2:左侧的整数 3 无法隐式转换为 Rational 类型。
    • 定义为非成员函数后,编译器可以通过构造函数将 23 转换为 Rational 类型,支持上述用法。
  2. 成员函数的限制

    • 成员函数只能为显式参数(非隐式的 this 指针)提供类型转换。
    Rational operator*(const Rational& rhs); // 如果是成员函数
    // r1 * 2 合法,但 3 * r2 无法编译,因为调用对象 3 无法转换为 Rational 类型。
    
  3. non-member 函数的灵活性

    • non-member 函数的所有参数都是显式的,编译器可自由对它们进行类型转换,支持更广泛的操作形式。

结论

  1. 若所有参数(包括隐式的调用对象)都需要类型转换,应使用 non-member 函数。
  2. non-member 函数为类型转换提供了更多的灵活性,避免了成员函数的类型限制。
  3. 使用 non-member 函数时,仍可将其放入与类相关的命名空间中,以保持逻辑清晰。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值