оператор перегрузки + (C ++)

Привет, я работаю над перегрузкой +, но когда я пытаюсь сделать простой вызов, например

статистик a, b, c;

a = b+c;

Когда я делаю вышеуказанный вызов, он вылетает. и если я сделаю перегрузку =, он просто вернет ноль. вот часть моего кода. Спасибо за помощь, ребята!!!

FYI next_number (двойное значение) увеличивает динамический массив на 1 и помещает это значение в конец массива.

statistician  operator+(const statistician& left, const statistician& right) 
{
    statistician temp;

    if(left.m_iArraySize == 0)
    {
        return right;
    }
    else if(right.m_iArraySize == 0)
    {
        return left;
    }
    else
    {
        statistician temp;

        for(int i =0; i< left.m_iArraySize; i++)
        {
            temp.next_number(left.m_dSeqArray[i]);
        }

        for(int i =0; i< right.m_iArraySize; i++)
        {
            temp.next_number(right.m_dSeqArray[i]);
        }
        return temp;
    }

} 

Реализация класса

#include "Statistician.h"
#include <iostream>
using namespace std;


namespace main_savitch_2C
{

statistician::statistician()
{
    m_iArraySize=0;
    m_dSeqArray = new double[1]; // Preset our list to 1 items
    m_dSeqArray[0] = 0; 

}



statistician::~statistician()
{    
    delete[] m_dSeqArray;
    m_iArraySize=0;

}

statistician::statistician(const statistician &s)
{
    m_iArraySize=0;
    m_dSeqArray = new double[1]; // Preset our list to 1 items  
    m_dSeqArray[0] = 0;

}  

int statistician::ChangeArraySize(int iArraySize)
{


    double *iTempArray;
    iTempArray = new double[m_iArraySize];

    //Assert Data   
    assert(iArraySize >-1);
    // Copy the info of the array into a temp array

    for(int i = 0; i < m_iArraySize-1; i++)
    {

        iTempArray[i] = m_dSeqArray[i];
    }
//    iTempArray = m_dSeqArray;
    // delete the array 

    delete[] m_dSeqArray;



    m_dSeqArray = new double[iArraySize];



    // Copy the info of the temp array  back into the orginal array variable

    for(int i = 0; i < m_iArraySize; i++)
    {

        m_dSeqArray[i] = iTempArray[i];
    }
    m_dSeqArray[iArraySize-1]=0;

    // Free our TempArray
    delete[] iTempArray;

    return 0;
}

//length
int statistician::length() const
{
    if(m_iArraySize == 0) {return 0;}

    return m_iArraySize;
}

//sum()
double statistician::sum() const
{
   if(m_iArraySize == 0) {return 0;}     

    long double dSum=0; 
    for(int i = 0; i < m_iArraySize; i++)
    {
        dSum = dSum + m_dSeqArray[i];
    }
    return dSum;
}

//mean()
double statistician::mean() const
{ 
    if(m_iArraySize == 0) {return 0;}

    double dSum,dMean; 
    int iCounter; 

    dSum=0;
    dMean=0;
    iCounter=0;

    for(int i = 0; i < m_iArraySize; i++)
    {

        dSum = dSum + m_dSeqArray[i];
        iCounter++;
    }

    // Check for Dividing by zero 
    if(dSum == 0)
    {
        dMean = 0; 
    }
    else 
    {
        dMean = dSum/iCounter; 
    }
    return dMean;

}

//reset()
int statistician::reset()
{

    delete[] m_dSeqArray;


    m_iArraySize = 0;

    m_dSeqArray = new double[1];
    m_dSeqArray[0] = 0;

    return 0;
}

//next_number(i)
int statistician::next_number(double iValue)
{
    // Ensure that size of the array has not somehow become negative 


    m_iArraySize++;

    if(m_iArraySize > 1)
    {

        ChangeArraySize(m_iArraySize);
        m_dSeqArray[m_iArraySize-1] = iValue;



    }
    else 
    {

        m_dSeqArray[m_iArraySize-1] = iValue;


    }



    return 0;
}

//next_number(int iValue)
int statistician::next_number(int iValue)
{


    m_iArraySize++;

    if(m_iArraySize > 1)
    {

        ChangeArraySize(m_iArraySize);
        m_dSeqArray[m_iArraySize-1] = iValue;



    }
    else 
    {

        m_dSeqArray[m_iArraySize-1] = iValue;


    }

    return 0;
}

//next_number(char iValue) in case a character is passed 
int statistician::next_number(char iValue)
{
     cout << "Invalid value passed to next_number!" <<endl;

    return 0;
}

//Minimum


double statistician::minimum() const
{
 if(m_iArraySize == 0) {return 0;}

    double dMinimum = m_dSeqArray[0];
    for(int i = 0; i < m_iArraySize; i++)
    {

        if(m_dSeqArray[i] < dMinimum)
        {
            dMinimum = m_dSeqArray[i];

        }     
    }
    return dMinimum;
}

//Maximum
double statistician::maximum() const
{
    if(m_iArraySize == 0) {return 0;}

    double dMaximum = m_dSeqArray[0];
    for(int i = 0; i < m_iArraySize; i++)
    {

        if(m_dSeqArray[i] > dMaximum)
        {
            dMaximum = m_dSeqArray[i];

        }     
    }
    return dMaximum;

}

//Operator Overloading
/*
statistician statistician::operator=( statistician& left)
{
    cout << left.sum();
    cout << left.length();
    cout << this->sum();

    if(this != &left)
    {
        this->reset();
        for (int i =0; i < left.m_iArraySize; i++)
        {
            this->next_number(left.m_dSeqArray[i]);
            cout<<this->next_number(left.m_dSeqArray[i]) <<endl;
            cout<<left.next_number(left.m_dSeqArray[i]) <<endl;
        }
    }
    return *this;


} */
statistician  operator+(const statistician& left, const statistician& right)
{
    statistician temp;

    if(left.m_iArraySize == 0)
    {
        return right;
    }
    else if(right.m_iArraySize == 0)
    {
        return left;
    }
    else
    {
        statistician temp;

        for(int i =0; i< left.m_iArraySize; i++)
        {
            temp.next_number(left.m_dSeqArray[i]);
        }

        for(int i =0; i< right.m_iArraySize; i++)
        {
            temp.next_number(right.m_dSeqArray[i]);
        }
        return temp;
    }

} 


bool  operator==( const statistician& left,const   statistician& right)
{ 
    cout << "L length = : "<<left.length() <<" R Length: "<< right.length()<<endl;
    if(left.length() != right.length()) { return false; }

        cout << "L minimum = : "<<left.minimum() <<" R minimum: "<< right.minimum()<<endl;
    if(left.minimum() != right.minimum()) { return false; }

    cout << "L maximum = : "<<left.maximum() <<" R maximum: "<< right.maximum()<<endl;
    if(left.maximum() != right.maximum()) { return false; }

    cout << "L sum = : "<<left.sum() <<" R sum: "<< right.sum()<<endl;
    if(left.sum() != right.sum() ) {return false; }

    cout << "L mean = : "<<left.mean() <<" R mean: "<< right.mean()<<endl;
    if(left.mean() != right.mean() ) {return false; }  






    return true;

}


} // End of Namespace 

и .h ....

#ifndef StatClass
#define StatClass
#include <cassert>


namespace main_savitch_2C
{



class  statistician     //With copy constructor
{
  public:

    // Constructor
    statistician();


    //Deconstructor 
    ~statistician();

    //Copy constructor      
    statistician(const statistician &s);

    //length
    int length() const;

    //sum()
    double sum() const;

    //mean()
    double mean() const;

    //reset()
    int reset();

    //next_number(i)
    int next_number(double iValue);
    int next_number(int iValue);
    int next_number(char iValue);

    //Minimum

    double minimum() const;

    //Maximum
    double maximum() const;


    //Operator Overloading
    //statistician operator=(statistician& left);
    friend statistician operator+(const statistician& left, const statistician& right);
    friend bool operator==(const statistician& left, const statistician& right); 





  private:
    // Private Variables
    double *m_dSeqArray;
    int m_iArraySize;

    // Private Functions
    int ChangeArraySize(int iArraySize);





};

};  
#endif

person Darxval    schedule 29.08.2010    source источник
comment
Ваше первое объявление statistician temp бесполезно.   -  person Cedric H.    schedule 30.08.2010
comment
Как выглядят конструктор и переменные-члены statistician? Инициализирует ли конструктор m_iArraySize?   -  person Steve Jessop    schedule 30.08.2010
comment
Невозможно сказать, что происходит, без полного кода. Словесное описание того, что делает часть недостающего кода, не очень полезно, когда весь вопрос здесь исключительно потому, что ваш код не делает то, что вы ожидаете.   -  person Steve Townsend    schedule 30.08.2010
comment
Пожалуйста, опубликуйте код для конструктора по умолчанию statistician, это имеет отношение к поведению кода, который вы опубликовали. Кроме того, что это за тип m_dSeqArray?   -  person Johnsyweb    schedule 30.08.2010
comment
Нам нужно больше узнать о классе и его конструкторах. Но в основном похоже, что у вас есть указатель RAW, который вы неправильно используете.   -  person Martin York    schedule 30.08.2010
comment
извините за это, я добавил файл реализации класса, это фактически арифметический класс, который проверяет сумму, среднее значение, длину, максимум, минимум   -  person Darxval    schedule 30.08.2010
comment
Но не Statistician.h? Вы действительно не упрощаете это.   -  person Beta    schedule 30.08.2010
comment
Вы можете складывать статистиков и умножать их? stackoverflow.com/questions/3588372/   -  person CB Bailey    schedule 30.08.2010
comment
я не могу их добавить. хотя я могу проверить равенство   -  person Darxval    schedule 30.08.2010
comment
Ваш код станет значительно проще и менее подверженным ошибкам, если вы измените m_dSeqArray на std::vector<double>.   -  person Steve Jessop    schedule 30.08.2010
comment
Вам нужен оператор assignemnt. Значение по умолчанию вызовет проблемы с классами, имеющими указатели RAW. Хотя вы можете решить все проблемы с помощью внутреннего использования std :: vector.   -  person Martin York    schedule 30.08.2010


Ответы (3)


Если вы не определяете оператор присваивания (operator=), то компилятор предоставляет версию по умолчанию, которая делает неглубокую копию, то есть копирует указатель m_dSeqArray, но не то, на что он указывает к. Поэтому, когда вы его используете, вы получаете два указателя, указывающие на одно и то же. Когда два статистика выходят за пределы области видимости, каждый из них вызывает деструктор, который дважды пытается удалить массив, БУМ!

Ваша версия оператора присваивания копирует каждый элемент дважды:

this->next_number(left.m_dSeqArray[i]);
cout<<this->next_number(left.m_dSeqArray[i]) <<endl;

Таким образом, результирующий статистик должен выглядеть странно, но не быть пустым (если только назначенный статистик не был пуст, как в вашем примере).

person Beta    schedule 29.08.2010

Во-первых, канонический operator+ должен быть реализован в терминах operator+=, и именно в этом операторе вы должны написать свою логику.

Во-вторых, statistician конструктор копирования ничего не копирует, он просто создает statistician по умолчанию. Поскольку operator+ использует конструктор копирования для своего возвращаемого значения, вы никогда не получите то, что намеревались.

В-третьих, statistician::next_number() не делает того, что вы думаете. Вы никогда не увеличиваете размер внутреннего массива, поэтому вы выйдете за пределы. Это приводит к неопределенному поведению, возможно, к сбою при перезаписи памяти, принадлежащей другим объектам.

Я не проверил весь код для всех методов, но вам обязательно нужно исправить эти три ошибки, прежде чем продолжить. Что ж, первый не так важен, но два других необходимы.

person Gorpik    schedule 29.08.2010
comment
так что ChangeArraySize (m_iArraySize), который я вызываю в next_number, не увеличивает его? Что касается конструктора копирования, я не думаю, что эффективно пишу его, я изменил его на это: m_iArraySize = s.m_iArraySize; m_dSeqArray = новый двойной [1]; но поскольку оператор + использует конструктор копирования, означает ли это, что m_dSeqArray отображается как массив [0]. со значением инициализации навсегда? - person Darxval; 30.08.2010
comment
Поскольку m_iArraySize на единицу меньше фактического размера массива, вы просто обнуляете значение последнего элемента в массиве в ChangeArraySize(). И если бы вы на самом деле не реализовывали конструктор копии, ваша копия будет использовать исходный внутренний массив объекта. Когда вы удаляете этот массив в деструкторе исходного объекта (после выхода из operator+), вы получаете удаленный массив в копии (рецепт катастрофы). Ваша новая реализация не дает сбоев, но и не копирует массив. - person Gorpik; 30.08.2010

Хотя это и не прямая причина сбоя, я не могу не указать на это

Конструктор копирования выглядит как копирование конструктора. Я считаю, что это может быть неправильным. Конструктор копирования может быть задействован, поскольку оператор + включает возврат копии, которая может вызвать конструктор копии, если она не будет удалена.

Как вы используете 's' в конструкторе копирования?

statistician::statistician(const statistician &s) 
{ 
    m_iArraySize=0; 
    m_dSeqArray = new double[1]; // Preset our list to 1 items   
    m_dSeqArray[0] = 0; 
}
person Chubsdad    schedule 30.08.2010