代码之家  ›  专栏  ›  技术社区  ›  user9267359

Rational类和移动语义不起作用

  •  0
  • user9267359  · 技术社区  · 7 年前

    我试图在问题中为已经给定的类(答案为@Aak)添加更多功能: How to output fraction instead of decimal number? 用于在中打印分数 numerator / denominator .

    首先,给定的代码在没有任何更改的情况下无法工作。然后我在做了一些更改后使其工作。然而,我的实现给了我一个错误的输出。

    例如:

    input: A = 3;
           B = 3;
    Output: 9/1
            9
    instead of: 1
    

    以下是完整的实现:

    #include <iostream>
    /********************** Rational class **********************************/
    class Rational
    {
    private:
        int m_numerator, m_denominator;
    private:
        inline void simplificate()
        {
            int commondivisor = 1;
            for(int i=2;i<= std::min(abs(m_numerator), abs(m_denominator));i++)
                if( m_numerator%i == 0 && m_denominator%i == 0 )
                    commondivisor = i;
            m_numerator /= commondivisor;
            m_denominator /= commondivisor;
        }
    
    public:
        Rational()                                  // Defualt
            :m_numerator(1), m_denominator(1)
            {}
    
        Rational(const int& num, const int& den=1)  // Parameterized
            :m_numerator(num), m_denominator(den)
            {}
    
        Rational(const Rational& other)             // Copy
            :m_numerator(other.m_numerator), m_denominator(other.m_denominator)
            {}
    
        /*Rational(Rational&& other)                  // Move
            :m_numerator(other.m_numerator), m_denominator(other.m_denominator)
            {}*/
    
        ~Rational(){}
    
        Rational& operator/ (const int& divisor)
        {
                m_denominator *= divisor;
                simplificate();
                return *this;
        }
        Rational& operator/ (const Rational &divisor)
        {
                m_numerator *= divisor.m_numerator;
                m_denominator *= divisor.m_denominator;
                simplificate();
                return *this;
        }
        const double getrealformat()const
        {
            return  static_cast<double>(m_numerator)/
                    static_cast<double>(m_denominator);
        }
    
        friend double operator/ (Rational& obj, const int& divisor);
        friend void printRational(Rational& obj, const int& A, const int& B);
        friend void printRational(Rational& obj, const int&& A, const int&& B);
    };
    /************************** Friend functions ********************************/
    double operator/ (Rational& obj, const int& divisor)
    {
        obj.m_denominator *= divisor;
        obj.simplificate();
        return obj.getrealformat();
    }
    void printRational(Rational& obj, const int& A, const int& B)   // lvalue
    {
        Rational r1(A), r2(B);
        obj = r1/r2;
        std::cout<<obj.m_numerator<<'/'<<obj.m_denominator<<std::endl;
        std::cout<<obj.getrealformat()<<std::endl;
    }
    void printRational(Rational& obj, const int&& A, const int&& B)  // rvalue
    {
        Rational r1(A), r2(B);
        obj = r1/r2;
        std::cout<<obj.m_numerator<<'/'<<obj.m_denominator<<std::endl;
        std::cout<<obj.getrealformat()<<std::endl;
    }
    /*****************************************************************************/
    int main()
    {
        Rational obj;
        printRational(obj, 3,3);
        return 0;
    }
    

    问题1:逻辑看起来不错,但我不知道为什么我得到了错误的答案。有人能找到问题吗?

    问题2:我已经为这个类编写了“Move”构造函数,您可以在评论部分找到。但是,由于以下错误,我无法使用它:

    D:\Programming\C++\CPP Programs\Class - Fractions\Class - Fractions.cpp|70|error: use of deleted function 'Rational& Rational::operator=(const Rational&)'|
    
    D:\Programming\C++\CPP Programs\Class - Fractions\Class - Fractions.cpp|77|error: use of deleted function 'Rational& Rational::operator=(const Rational&)'|
    

    (据我所知,无论何时调用,移动的对象/实例都会被销毁。)

    有人能帮我实现这个类的Move构造函数吗?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Community CDub    4 年前

    看看你的 operator/()

    Rational& operator/ (const Rational &divisor)
    {
            m_numerator *= divisor.m_numerator;
            m_denominator *= divisor.m_denominator;
            simplificate();
            return *this;
    }
    

    此代码适用于 operator*() ,不适用于 操作员/() .

    大概

            m_numerator *= divisor.m_denominator;
            m_denominator *= divisor.m_numerator;
    

    但更糟糕的是 操作员/() 修改对象。

    您的代码(已更正的切换分子和分母)应正确 operator/=() ,不适用于 操作员/() 应该返回一个新对象。

    我建议如下

    Rational& operator/= (const Rational &divisor)
    {
            m_numerator *= divisor.m_denominator;
            m_denominator *= divisor.m_numerator;
            simplificate();
            return *this;
    }
    
    friend Rational operator/ (Rational A, Rational const & B);
    

    在课堂之外,

    Rational operator/ (Rational A, Rational const & B)
     { return A/=B; }
    

    关于问题2(“我已经为类编写了“Move”构造函数,[…]但是,由于以下错误,我无法使用它”),您可以在中看到 this page 那个

    如果满足以下任一条件,则类T的隐式声明的复制赋值运算符定义为已删除:

    • T有一个用户声明的move构造函数;
    • T有一个用户声明的移动赋值运算符。

    因此,在定义移动构造函数时,将删除隐式复制操作符。

    您可以解决添加的问题

     Rational & operator= (Rational const &) = default;
    

    重新激活隐式复制构造函数