zoukankan      html  css  js  c++  java
  • Effective C++学习之若所有参数皆需类型转换,请为此采用nonmember函数

    假如我们有以下的有理数类:

    class Rational {
    public:
        Rational(int numerator = 0, int denominator = 1);
    
        int getnumerator() const;
        int getdenominator() const;
    private:
        int numerator;
        int denominator;
    };

    在条款19中提到过设计class犹如设计type,也就是说我们的Rational类应该提供类似int类型的功能,因此我们必须添加一些运算符重载函数,标准的教科书函数是这样的,你将自己的重载函数声明为了一个类的成员函数,对一些设计来说这样是可以工作的,比如一下的代码:  

    Rational oneEight(1, 8);
    Rational oneHalf(1, 2);
    Rational result = oneHalf*oneEight;

    作为一个有理数类我们希望他可以和一个整数相乘,于是我们就写出了以下的代码:

    result = oneHalf * 2;
    result = 2 * oneHalf;

    第一行的代码能够很好的工作,Oops!!!第二行的地方崩溃了,GCC会给出好几屏的错误提示,这点让人崩溃。下面就来简单分析一下为什么一个第一表达式能够正常运行,而第二个表达式不能正常运行。这次就是发生了所谓的隐士类型转换,编译器发现函数形参是一个Rational而实参是一个int后就给你做了隐士的类型转换,于是乎就有了类似以下的代码,他先用实参构造了一个Rational对象,然后再参与到函数中。

    const Rational temp(2);
    result = oneHalf *temp

    对于第二个表达式编译器就无能为力了,2是一个常量他压根就没有this指针也就无法调用类的成员函数。

    C++的有些特性很是让人难受,编译器会在你不经意见来一个类型转换。

    要实现完全和内置类型一样的乘法,我们有两种手段一种是将运算符重载为类的友元函数:

    class Rational {
    public:
        Rational(int numerator = 0, int denominator = 1);
    
        int getnumerator() const;
        int getdenominator() const;
    friend const Rational operator*(const Rational& lhs, const Rational& rhs);
    private:
        int numerator;
        int denominator;
    };

    而另外一种方式就是将重载运算符的函数声明为一个non-member函数:

    class Rational {
    public:
        Rational(int numerator = 0, int denominator = 1);
    
        int getnumerator() const;
        int getdenominator() const;
    private:
        int numerator;
        int denominator;
    };
    const Rational operator*(const Rational& lhs, const Rational& rhs);

    当我看到第二种方式的写法时,对一直将这些函数写成友元函数的我有点小震惊,之后想想这样的设计比起将其声明为友元函数更具有优点,最起码的你不用担心友元函数会破坏你的内部成员了。

    这一条给了我一下的启示:  

      1. 这一条给人的第一感觉就是不要固守在别人给你的限定里,该这样做的时候就应该相信自己,有些东西可能违反一些常规,但那是最有效的。

      2.在这一点也体现了提供对原始资源的访问是必须的。这样就可能减少使用friend的次数,避免friend 对数据的破坏是很有必要的。

     

  • 相关阅读:
    软件测试之po设计模式
    Python_标识符及命名规范
    python基础(第一个python程序)
    计算机基础知识
    注册界面测试案例
    vscode使用-添加格式化插件
    工作-提交review失败
    工作-大首页走测试环境
    jquery--选择器 第几
    a标签href无值,点击刷新页面解决办法
  • 原文地址:https://www.cnblogs.com/lzh2nix/p/3087964.html
Copyright © 2011-2022 走看看