美文网首页Exceptional C++
【Exceptional C++(9)】CLASS技术

【Exceptional C++(9)】CLASS技术

作者: downdemo | 来源:发表于2018-01-29 11:57 被阅读4次

    问题

    • 下面的class有一些不好的代码风格和错误,找出来
    class Complex
    {
    public:
        Complex(double real, double imaginary = 0)
          :  _real(real), _imaginary(imaginary)
        {}
        void operator+(Complex other)
        {
            _real = _real + other._real;
            _imaginary = _imaginary + other._imaginary;
        }
        void operator<<(ostream os)
        {
            os << "(" << _real << "," << _imaginary << ")";
        }
        Complex operator++()
        {
            ++_real;
            return *this;
        }
        Complex operator++(int)
        {
            Complex temp = *this;
            ++_real;
            return temp;
        }
    private:
        double _real, _imaginary;
    };
    

    解答

        Complex(double real, double imaginary = 0)
          :  _real(real), _imaginary(imaginary)
        {}
    
    • 构造函数允许发生隐式转换,由于第二个参数有默认值,此函数可以看作单一参数的构造函数,并因此得允许一个double转换为Complex,这样的转换可能并非意图之中,所以把构造函数设为explicit比较好
        void operator+(Complex other)
        {
            _real = _real + other._real;
            _imaginary = _imaginary + other._imaginary;
        }
    
    • operator+使用pass-by-value,效率低,尽量用const&传参,此外a=a+b应该写成a+=b,这样做对double的加法虽然没什么提升,但是对class的加法效率改善很明显
    • 尽量写a op=b而不要写a=a op b。因为operator+=直接作用于左件,且传回的是引用,而operator+必须传回一个临时对象
    T& T::operator+=(const T& other)
    {
        // ...
        return *this;
    }
    const T operator+(const T& a, const T& b)
    {
        T temp(a);
        temp += b;
        return temp;
    }
    
    • 如果提供了某个子运算(如operator+)的标准版,请同时提供一个assignment版(如operator+=)
    • operator+不应该是member function,当允许其他类别隐式转换为Complex时,operator+可能无法正常工作,比如对Complex对象只能写a = b + 1.0而不能写a = 1.0 + b,因为member operator+要求左件为Complex
    • 使用以下准则决定一个运算是否为member function
      • 一元运算子应该是member
      • = () [] -> 必须是member
      • assignment版运算子(+= -= *= /=)都必须是member
      • 其他所有二元运算子都应该是nonmember
    • operator<<不应该成为mmeber function,且应该传回ostream&
        Complex operator++()
        {
            ++_real;
            return *this;
        }
    
    • 前置累加运算子应该传回reference to non-const,所以返回类型应是Complex&
        Complex operator++(int)
        {
            Complex temp = *this;
            ++_real;
            return temp;
        }
    
    • 后置累加运算子应传回const Complex,这样可以阻止类似于a++++的代码
    • 后置累加运算子应该以前置累加运算子为本
    • 避免触及保留名称,不要在变量名前加下划线,可以加在后面
    • 下面是修改后的版本
    class Complex
    {
    public:
        explicit Complex(double real, double imaginary = 0)
          :  real_(real), imaginary_(imaginary)
        {}
        // 定义operator+=,将operator+设为non-member
        Complex& operator+=(const Complex& other)
        {
            real_ += other.real_;
            imaginary_ += other.imaginary_;
            return *this;
        }
        Complex& operator++()
        {
            ++real_;
            return *this;
        }
        Complex operator++(int)
        {
            Complex temp(*this);
            ++*this;
            return temp;
        }
        // 定义Print
        ostream& Print(ostream& os) const
        {
            return os << "(" << real_ << "," << imaginary_ << ")";
        }
    private:
        double real_, imaginary_;
    };
    const Complex& operator+(const Complex& lhs, const Complex& rhs)
    {
        Complex ret(lhs);
        ret += rhs;
        return ret;
    }
    ostream& operator<<(ostream& os, const Complex& c)
    {
        return c.Print(os);  
    }
    

    相关文章

      网友评论

        本文标题:【Exceptional C++(9)】CLASS技术

        本文链接:https://www.haomeiwen.com/subject/myfxzxtx.html