欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > Effective C++读书笔记——item24(非成员函数的用途)

Effective C++读书笔记——item24(非成员函数的用途)

2025/1/23 21:36:44 来源:https://blog.csdn.net/weixin_46032775/article/details/145309920  浏览:    关键词:Effective C++读书笔记——item24(非成员函数的用途)

一、核心要点

  • 当一个函数的所有参数都需要进行类型转换才能调用该函数时,这个函数应该被定义为 non-member 函数,而不是 member 函数。

二、详细解释

  1. 类型转换和成员函数调用

    • 对于成员函数,在调用时,编译器只会对调用该函数的对象(通过 this 指针指向的对象)进行隐式类型转换,而对于成员函数的参数不会自动进行隐式类型转换(除非参数在参数列表中明确允许转换)。
    • 例如,假设有一个有理数类 Rational 和一个乘法运算符 operator* 作为成员函数:
     
    class Rational {
    public:Rational(int numerator = 0, int denominator = 1);  // 构造函数const Rational operator*(const Rational& rhs) const;
    private:int n, d;  // 分子和分母
    };
    
     

    当执行 Rational oneHalf(1, 2); 和 oneHalf * 2; 时,2 会被隐式转换为 Rational 类型,因为 oneHalf 是调用 operator* 的对象,编译器会为它进行隐式类型转换。但对于 2 * oneHalf;,编译器不会将 2 转换为 Rational 类型,因为 2 不是调用 operator* 的对象,这里 operator* 是 Rational 的成员函数,编译器不会自动对参数进行隐式类型转换,会导致编译错误。

  2. 使用 non-member 函数解决问题

    • 将 operator* 定义为 non-member 函数可以解决上述问题,因为对于 non-member 函数,编译器会对所有参数进行隐式类型转换。
     
    class Rational {
    public:Rational(int numerator = 0, int denominator = 1);  // 构造函数
    private:int n, d;  // 分子和分母
    };
    const Rational operator*(const Rational& lhs, const Rational& rhs) {return Rational(lhs.n * rhs.n, lhs.d * rhs.d);
    }
    
     

    这样,当执行 2 * oneHalf 时,2 会被隐式转换为 Rational 类型,因为 operator* 是 non-member 函数,编译器会对所有参数尝试隐式类型转换,使得代码可以正常运行。

  3. 与封装性的关系

    • 这并不影响封装性,因为 non-member 函数仍然可以通过 Rational 的 public 接口(例如构造函数和 public 成员函数)来操作 Rational 类的对象。
    • 同时,non-member 函数可以是 Rational 的友元函数,如果它需要访问 Rational 的 private 或 protected 成员,但通常不需要,仅通过 public 接口就能完成操作。
  4. 友元函数的考虑

    • 虽然 non-member 函数可以是友元函数,但一般情况下,尽量避免使用友元函数,除非确实需要访问类的 private 或 protected 成员。通常仅通过 public 接口就能实现功能,这样可以保持更好的封装性。
  5. 示例说明

    • 假设还有一个类 Matrix,以及 operator* 用于矩阵乘法:
     
    class Matrix {
    public:Matrix(int rows, int cols);// 其他成员函数
    };
    Matrix operator*(const Matrix& lhs, const Matrix& rhs);
    
     

    如果 Matrix 的构造函数允许将整数转换为 Matrix 类型(例如单位矩阵),那么 operator* 作为 non-member 函数,可以让以下代码正常工作:

    Matrix m1(2, 2);
    Matrix m2 = m1 * 2;  // 从 2 隐式构造一个合适的 Matrix
    Matrix m3 = 2 * m1;  // 从 2 隐式构造一个合适的 Matrix
    
     

    而如果 operator* 是 Matrix 的成员函数,只有 m1 * 2 可能正常工作,2 * m1 会导致编译错误,因为编译器不会自动对 2 进行类型转换。

三、总结

  • 当一个函数的所有参数都需要进行类型转换才能正常调用时,将该函数定义为 non-member 函数可以使编译器自动对所有参数进行类型转换,提高代码的灵活性和一致性。
  • 这种做法不会破坏封装性,并且在很多情况下可以让代码更符合用户的使用习惯,避免因成员函数调用的限制导致的某些调用无法进行隐式类型转换的问题。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com