【问题标题】:Copy Operator not working properly复制运算符无法正常工作
【发布时间】:2018-04-23 17:09:06
【问题描述】:

您好,我正在研究一个多项式课程。我对复制 (=) 运算符重载有疑问。让我举一些例子。

假设我有:

P = 2x^6 + 4x^5 + 2x^3 + 3x^2 + 2x + 1

如果我做 P=P 我得到:

P 4x^6 + 8x^5 + 4x^3 + 6x^2 + 4x + 2

我也得到了 P = Q*P 的东西。我认为我的方法没有任何问题,也许是其他问题。

#include <iostream>
#include <cmath>

using namespace std;

class Polynomial {
protected:
    class Term {
    public:
        int exponent;
        int coefficient;
        Term *next;

        Term(int exp, int coeff, Term *n) {
            exponent = exp;
            coefficient = coeff;
            next = n;
        }
        ~Term(){
            delete next;
        }

        friend class Polynomial;

        friend ostream;
    };

public:
    Polynomial() {
        root = NULL;
    }

    Polynomial(const Polynomial &p) {
        Term *target = p.root;
        root = NULL;
        while (target != NULL) {
            this->addTerm(target->exponent, target->coefficient);
            target = target->next;
        }
    }

    ~Polynomial() {
        delete root;
    }

    Polynomial & operator = (const Polynomial &p){
        Term *target = p.root;
        while (target!=NULL){
            this->addTerm(target->exponent , target->coefficient);
            target = target->next;
        }
        return *this;
    }

    void addTerm(int expon, int coeff) {

        Term *prev = root;
        Term *target = root;

        if (root == NULL) {
            Term *p = new Term(expon, coeff, target);
            //Term *p = &tmp;
            root = p;
            return;
        }

        while (target != NULL && target->exponent > expon) {
            prev = target;
            target = target->next;
        }

        if (target && target->exponent == expon) {
            target->coefficient += coeff;
            if (target->coefficient == 0) {
                prev->next = target->next;
            }
            return;
        }

        if (target == root) {
            Term *p = new Term(expon, coeff, target);
            root = p;   //Set p as root
        } else {

            Term *p = new Term(expon, coeff, target);
            prev->next = p;


        }


    }

    double evaluate(double x) {
        Term *target = root;
        double sum=0;
        while (target != NULL) {
            sum += target->coefficient * pow(x, target->exponent);
            target = target->next;
        }
        return sum;
    }

    friend Polynomial operator+(const Polynomial &p, const Polynomial &q) {
        Polynomial tmp;
        Term *target = p.root;

        while (target != NULL) {
            tmp.addTerm(target->exponent, target->coefficient);
            target = target->next;

        }
        target = q.root;
        while (target != NULL) {
            tmp.addTerm(target->exponent, target->coefficient);
            target = target->next;
        }
        return tmp;

    }

    friend Polynomial operator * (const Polynomial &p, const Polynomial &q) {
        Polynomial tmp;
        Term *target_1 = p.root;
        Term *target_2 = q.root;
        while (target_1 != NULL) {
            while (target_2 != NULL) {

                tmp.addTerm(target_1->exponent + target_2->exponent, target_1->coefficient * target_2->coefficient);

                target_2 = target_2->next;
            }
            target_2 = q.root;
            target_1 = target_1->next;
        }
        return tmp;
    }


    friend ostream &operator << (ostream &out, const Polynomial &p) {
        Term *target = p.root;
        if (target!=NULL && target->coefficient < 0) cout<<"- ";

        while (target != NULL) {
            if (target->exponent){
                if (abs(target->coefficient) != 1) out << abs(target->coefficient);
            }
            else {
                out << abs(target->coefficient);
            }
            out << (target->exponent ? (target->exponent != 1 ? "x^" : "x") : "");
            if (target->exponent) {
                if (target->exponent != 1) out << target->exponent;
            }
            target = target->next;
            if (target!= NULL) {
                if (target->coefficient > 0){
                    out<<" + ";
                }
                else{
                    out <<" - ";
                }
            }


        }


        return out;
    }

private:
    Term *root;
};

#ifndef CONTEST
int main(){

    Polynomial P;
    P.addTerm(6,2);
    P.addTerm(5,4);
    P.addTerm(3,2);
    P.addTerm(2,2);
    P.addTerm(1,2);
    P.addTerm(2,1);
    P.addTerm(0,1);

    cout<<P<<endl;

    cout<<P.evaluate(0)<<endl;
   // Polynomial Q = P;

    //Polynomial S = Q*P;
    P = P;

    //cout<<S<<endl;
    cout<<P<<endl;
}

#endif

【问题讨论】:

  • 也许只有我一个人,但在您的复制构造函数和= 运算符定义中,您先执行Term *target = p.root;,然后执行while (target!=NULL){ this-&gt;addTerm(target-&gt;exponent , target-&gt;coefficient);。如果 LHS 不是空多项式,那不是将 RHS 添加到 LHS 吗?

标签: c++ oop operator-overloading


【解决方案1】:

您的operator= 不正确:赋值应该替换当前多项式中的项,而不是添加到它们。您需要先清除分配给的对象:

delete root;
root = nullptr;

这样做需要防止自我分配。所以用这个开始你的赋值运算符:

if (this == &p) return *this;

然后清除*this,然后照常复制p


另一种解决方案是重用您已经为复制构造函数所做的工作,并将copy-and-swap idiom 用于赋值运算符。这需要:

  1. 为你的类定义一个交换函数:

    friend void swap(Polynomial &lhs, Polynomial &rhs)
    {
      std::swap(lhs.root, rhs.root);
    }
    
  2. 更改operator= 以按值获取其参数,并在内部进行交换:

    Polynomial& operator=(Polynomial p)
    {
      swap(*this, p);
      return *this;
    }
    

这样,对象p将由复制构造函数初始化创建,然后与被分配的多项式交换(沿途传递其值),最后在operator=结束时销毁,方便照顾清理分配给多项式的旧值。

【讨论】:

  • 我明白了。我可以在 operator= 中创建一个新的 Polyminal 吗?哪个更优
  • @StavrosAvramidis 轻松实现operator= 的一种常用方法是copy-and-swap idiom。您只需要为您的类实现swap(两个根的简单交换),按值获取operator= 参数,然后与之交换。
  • 好的,谢谢!!,通过我的析构函数可以吗??我有一个人抱怨它,但删除了他的答案..?
猜你喜欢
  • 2015-11-27
  • 2015-04-25
  • 1970-01-01
  • 2021-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-11
  • 1970-01-01
相关资源
最近更新 更多