Другое > Hard'n'Soft
Програмирование на C++
<< < (9/25) > >>
gepar:
Но как сделать проверку что это не самоприсваивание, больше вникать никуда не надо, мне нужно лишь проверить что объект класса не присваивается самому себе, всё остальное работает.

Остальное кстати вот:

--- Код: ---# include <iostream>
# include <iomanip>
using namespace std;

class Array
{
friend ostream &operator<<(ostream &output, Array &test);
friend ostream &operator>>(ostream &output, Array &test);
public:
    //конструктор по умолчанию
    Array(int a, int b)
    {
        row=(a>0) ? a:1;
        column=(b>0)? b:1;
        ptr= new int [row*column+1];
        for (int i=1;i<row*column+1;i++)
         ptr[i]=0;
    }

    //конструктор копии в который я не могу добавить проверку на самоприсваивание
    Array (const Array &abc)
    {
            if (row!=abc.row || column!=abc.column)
            {
                delete []ptr;
                row=abc.row;
                column=abc.column;
                ptr=new int[row*column+1];
            }
            for (int i=0;i<row*column+1;i++)
             ptr[i]=abc.ptr[i];
    }

    //возможность обращения к нужному элементу массива
    int &operator()(int a, int b)
    {
        if ((a>0) && (a<=row) &&(b>0) && (b<=column))
         if (a==1)
          return ptr[a+b];
         else
          return ptr[(a-1)*column+b];
        else
         exit(100500);
    }

    //возможность обращения к нужному элементу массива для const объекта класса
    int &operator()(int a, int b) const
    {
        if ((a>0) && (a<=row) &&(b>0) && (b<=column))
         if (a==1)
          return ptr[a+b];
         else
          return ptr[(a-1)*column+b];
        else
         exit(100500);
    }

    //проверка на равенство
    bool operator==(Array test)
    {
        if ((row!=test.row) || (column!=test.column))
         return false;
        for (int j=0;j<row*column+1;j++)
         if (ptr[j]!=test.ptr[j])
          return false;
        return true;
    }

    //проверка на неравенство
    bool operator !=(Array test)
    {
        return !(*this==test);

    }



private:
    int row; //колличество строк
    int column; //колличество столбцов
    int *ptr; //указатель на массив с элементами int
};

ostream &operator<<(ostream &output, Array &test)
{
    output<<endl;
    for (int i=1;i<((test.row*test.column)+1);i++)
    {
        output<<setw(3)<<test.ptr[i]<<" ";
        if ((i)%test.column==0)
         output<<endl;
    }
    return output;
}

ostream &operator>>(ostream &output, Array &test)
{
    output<<endl;
    for (int i=1;i<((test.row*test.column)+1);i++)
     output<<setw(3)<<test.ptr[i]<<" ";
    output<<endl;
    return output;
}


int main()
{
    Array a(2,3);
    a(1,1)=3;
    a(2,2)=5;
    Array b(5,5);
    b(1,4)=10;
    b(3,3)=20;
    cout<<"a=b ? : "<<boolalpha<<(a!=b);
    cout<<"\nA:"<<a<<"B:"<<b;
    return 0;
}

--- Конец кода ---
Mr2:
gepar,
Ты понял почему писать if (*this!=abc); нельзя?
gepar:
Mr2,нет, я только понял что нельзя  :)
Mr2:

--- Цитата: gepar от 17 Март 2011, 00:48:52 ---Mr2,нет, я только понял что нельзя  :)

--- Конец цитаты ---
if можно писать двумя способами:
------------1-------------------
if(a!=b)
 cout << а <<endl;
------------2-----------------------
if(a!=b){
 cout << а <<endl;
 cout << а <<endl;
}
-------------------------------------
--------фатал эррор :D-------------
if(a!=b);
 cout << а <<endl;
-------------------------------------
 
gepar:
Mr2, а , ты об этом, я уже убирал ;, там не в ней дело, вот смотри:

--- Код: ---//свой класс-массив
//+ возможность получать min или max элемент массива
# include <iostream>
# include <iomanip>
# include <cstring>
using namespace std;

class Array
{
friend ostream &operator<<(ostream &output, Array &test);
friend ostream &operator>>(ostream &output, Array &test);
public:
    //конструктор по умолчанию
    Array(int a, int b)
    {
        row=(a>0) ? a:1;
        column=(b>0)? b:1;
        ptr= new int [row*column+1];
        for (int i=1;i<row*column+1;i++)
         ptr[i]=0;
    }

    //конструктор копии который не работает
    Array (const Array &abc)
    {
        if (*this!=abc)
        {
            if (row!=abc.row || column!=abc.column)
            {
                delete []ptr;
                row=abc.row;
                column=abc.column;
                ptr=new int[row*column+1];
            }
            for (int i=0;i<row*column+1;i++)
             ptr[i]=abc.ptr[i];
        }
        else exit(1);
    }

    //возможность обращения к нужному элементу массива
    int &operator()(int a, int b)
    {
        if ((a>0) && (a<=row) &&(b>0) && (b<=column))
         if (a==1)
          return ptr[a+b];
         else
          return ptr[(a-1)*column+b];
        else
         exit(100500);
    }

    //возможность обращения к нужному элементу массива для const объекта класса
    int &operator()(int a, int b) const
    {
        if ((a>0) && (a<=row) &&(b>0) && (b<=column))
         if (a==1)
          return ptr[a+b];
         else
          return ptr[(a-1)*column+b];
        else
         exit(100500);
    }

    //возможность нахождения min/max элемента
    int &operator()(string a)
    {
        if (a=="maximum")
        {
            int *max=&ptr[1];
            for (int i=1;i<row*column+1;i++)
             if (ptr[i]>*max)
              max=&ptr[i];
            return *max;
        }

        else if (a=="minimum")
        {
            int *min=&ptr[1];
            for (int i=1;i<row*column+1;i++)
             if(ptr[i]<*min)
              min=&ptr[i];
            return *min;
        }
        exit (1);
    }

    //проверка на равенство
    bool operator==(Array test)
    {
        if ((row!=test.row) || (column!=test.column))
         return false;
        for (int j=0;j<row*column+1;j++)
         if (ptr[j]!=test.ptr[j])
          return false;
        return true;
    }

    //проверка на неравенство
    bool operator !=(Array test)
    {
        return !(*this==test);

    }



private:
    int row; //колличество строк
    int column; //колличество столбцов
    int *ptr; //указатель на массив с элементами int
};

ostream &operator<<(ostream &output, Array &test)
{
    output<<endl;
    for (int i=1;i<((test.row*test.column)+1);i++)
    {
        output<<setw(3)<<test.ptr[i]<<" ";
        if ((i)%test.column==0)
         output<<endl;
    }
    return output;
}

ostream &operator>>(ostream &output, Array &test)
{
    output<<endl;
    for (int i=1;i<((test.row*test.column)+1);i++)
     output<<setw(3)<<test.ptr[i]<<" ";
    output<<endl;
    return output;
}


int main()
{
    Array a(2,3);
    a(1,1)=3;
    a(2,2)=5;
    Array b(5,5);
    b(1,4)=10;
    b(3,3)=20;
    cout<<"a=b ? : "<<boolalpha<<(a==b);
    cout<<"\nA:"<<a<<"B:"<<b;
    cout<<b("maximum");
    return 0;
}


--- Конец кода ---

Добавлено позже:
+ мне по прежнему интересно почему будет крешится программа с этой неправильной проверкой в конструкторе если в main он (констркутор копии) использоваться НЕбудет, но будет использоваться сравнение (== или !=). Вот сам попробуй убрать строку в main где используется сравнение и программа скомпилируется и будет работать нормально, но где же связь? Операции сравнения у меня никак не используют конструктор копии же.
Mr2:
Я не понимаю твой код. :(
Ты опиши проблему я мож чего найду.

--- Цитата ---//конструктор копии в который я не могу добавить проверку на самоприсваивание
--- Конец цитаты ---
Непонятно в каком случае происходит самокопирование?
Я читал что может быть неверное копирование связаное с адресами, а про само копирование не в курсе.
Пойду вникать в тонкости конструктора копирования. ;)
HoRRoR:
row*column+1 - зачем +1? Количество элементов матрицы NxM и равно NxM.
Непонятно, как ты используешь exit() без cstdlib.

--- Код: ---if (*this!=abc)

--- Конец кода ---
Ай-яй-яй, не делают так. К тому же, у тебя оператор сравнения перегружен. Сравнивают адреса:

--- Код: ---if (this!=&abc)

--- Конец кода ---

Чуть ниже:

--- Код: ---delete []ptr;

--- Конец кода ---
А что ты, собственно, удаляешь? Ты разве выделял память под этот ptr? Нафиг эту строку.
И вообще, замени

--- Код: ---bool operator==(Array test)
bool operator!=(Array test)

--- Конец кода ---
на

--- Код: ---bool operator==(const Array& test)
bool operator!=(const Array& test)

--- Конец кода ---
Негоже каждый раз для сравнения создавать копию массива.


--- Код: ---        if (a=="maximum")
...
        else if (a=="minimum")

--- Конец кода ---
Ну кто так делает? Это верх нерациональности. Заведи консанты или enum - {A_MAX, A_MIN}, принимай int или переменную типа этого enum'а, а там уже сравнивай или через switch выполняй необходимые действия.

Остальной код не смотрел, на этом всё заработало, дальше уж сам ищи ляпы.
gepar:

--- Цитата: HoRRoR ---row*column+1 - зачем +1? Количество элементов матрицы NxM и равно NxM.
--- Конец цитаты ---
да это я чтобы пропустить элемент 0.

--- Цитата: HoRRoR ---Непонятно, как ты используешь exit() без cstdlib.
--- Конец цитаты ---
Компилируется так - я и не использую  :)

--- Цитата: HoRRoR ---Ай-яй-яй, не делают так. К тому же, у тебя оператор сравнения перегружен. Сравнивают адреса:
--- Конец цитаты ---
Понял, буду знать.

--- Цитата: HoRRoR ---А что ты, собственно, удаляешь? Ты разве выделял память под этот ptr? Нафиг эту строку.
--- Конец цитаты ---
Ну а если у меня сначала было Array a(5,5) .... а потом уже a=b, следовательно место под a изначально было же выделено.
По поводу того чтобы не копировались мои массивы для сравнения исправлю, спасибо за подсказку.

--- Цитата: HoRRoR ---Ну кто так делает? Это верх нерациональности. Заведи консанты или enum - {A_MAX, A_MIN}, принимай int или переменную типа этого enum'а, а там уже сравнивай или через switch выполняй необходимые действия.
--- Конец цитаты ---
Не читал я ещё о enum, посмотрю что он из себя представляет. Через switch идея была сделать.
Ну и спасибо за конструктивную критику  :)
Mr2:
gepar,
А что ты хотел проверить в if (*this!=abc)?
Совпадают ли адрес нового(this) объекта с существующим(abc)?
 Вот нормальный массив:

--- Код: ---//Безопастный целочисленный массив.
//Автор Г. Шилдт.
#include <iostream>
#include <new>
#include <cstdlib>

using namespace std;

class array{
  int *p;
  int size;
 public:
  array(int cz){
   try{
    p = new int[cz];
    }
   catch(bad_alloc xa){
    cout << "error constr\n";
    exit(EXIT_FAILURE);
     }
    size = cz;
    }
  ~array(){
   delete[] p;
    }
  array(const array &a);
  void put(int i, int j){
   if(i>=0 && i<size) p[i] =j;
    }
  int get(int i){
   return p[i];
  }
};

array::array(const array &a){
 int i;
 try{
  p = new int[a.size];
   }
 catch(bad_alloc xa){
  cout << "Copy constr error\n";
  exit(EXIT_FAILURE);
   }
  for(i=0; i<a.size;i++)
   p[i] = a.p[i];
}

int main(){
 array num(10);
 int i;
 for(i = 0; i<10; i++)
  num.put(i,i);
 for(i=9; i>=0; i--)
  cout << num.get(i);
  cout << "\n";
 array x(num); //включаем копирующий конструктор.
 for(i=0; i<10; i++)
  cout<< x.get(i);
 cout <<"\n";
 system("pause");
 return 0;
}

--- Конец кода ---


gepar:
Mr2,да, я хотел проверить не будет ли самокопирование, которое может привести к ошибкам в некоторых случаях, ну да HoRRoR уже написал что нужно было адрес сравнивать, сейчас попробую поисправлять все те ошибки что я допустил.
Mr2:

--- Цитата: gepar ---Mr2,да, я хотел проверить не будет ли самокопирование,
--- Конец цитаты ---
В каком случае будет самокопирование? :?
array a;
    a=a;
ты об этом?
 
gepar:
Mr2,
array a;
a=a ну или a(a).
Mr2:

--- Цитата: gepar от 17 Март 2011, 16:08:17 ---Mr2,
array a;
a=a ну или a(a).

--- Конец цитаты ---
Я прочитал твою мысль на расстоянии. :lol:
Только непонятно кто будет делать такое присвоение, и какой смысл в нём. :?
gepar:
Mr2, смысл в том что это приведёт к неработоспособности программы, эдакая дыра, так зачем же её держать открытой?
Mr2:

--- Цитата: gepar от 17 Март 2011, 16:17:11 ---Mr2, смысл в том что это приведёт к неработоспособности программы, эдакая дыра, так зачем же её держать открытой?

--- Конец цитаты ---
Как я понял спровацировать её(ошибку) может только сам программист, пользователь(программы) по идее не может заставить объект самокопироваться. Ну а присвоить объект самому себе придёт в голову только особо извращённым индивидам. :lol:
 То же самое что
 int i = 3;
 i=i;
 :lol:
 
gepar:
Mr2,ну а если была ссылка на a, а потом уже и не помнишь что это ссылка на a и пытаешься этой ссылке присвоить a, а?  :)
Mr2:

--- Цитата: gepar от 17 Март 2011, 16:27:47 ---Mr2,ну а если была ссылка на a, а потом уже и не помнишь что это ссылка на a и пытаешься этой ссылке присвоить a, а?  :)

--- Конец цитаты ---
Да тебе определённо нужно сделать проверку. :)
 Вообще с выделением памяти, указателями  нужно быть аккуратнее и не пихать их везде где можно без них обойтись.
 Я их вообще редко использую.Ну просто необходимости особой не возникает.Я только сегодня вник в копирующий  конструктор, до этого просто знал что он есть и когда его нужно использовать. ^_^
gepar:

--- Цитата: Mr2 ---Вообще с выделением памяти, указателями  нужно быть аккуратнее и не пихать их везде где можно без них обойтись.
--- Конец цитаты ---
А это почему же?
Mr2:

--- Цитата: gepar от 17 Март 2011, 16:42:33 ---А это почему же?

--- Конец цитаты ---
Ну если твоя программа состоит из пары строк то ничего страшного.
 А вот если из пары сотен, то тут уже будет трудно найдти какой указатель шалит(заставляет аварийно завершиться программу)
 или почему кончилась память. Тем более если ты " не помнишь что это ссылка на a и пытаешься этой ссылке присвоить a". :)
HoRRoR:

--- Цитата ---да это я чтобы пропустить элемент 0.

--- Конец цитаты ---
Неоправданная избыточность информации - плохой тон. Уменьшай индекс на 1. А если ты перепишешь класс под шаблоны и в каком-либо случае у тебя элементами будут служить объекты по 100МБ?


--- Цитата ---Ну а если у меня сначала было Array a(5,5) .... а потом уже a=b, следовательно место под a изначально было же выделено.
По поводу того чтобы не копировались мои массивы для сравнения исправлю, спасибо за подсказку.

--- Конец цитаты ---
Во-первых, при создании присваивай переменной NULL, а при удалении делай так:

--- Код: ---if(ptr)
{
   delete []ptr;
   ptr = NULL;
}

--- Конец кода ---
В прочем, если ты тут же выделяешь память, то присваивать NULL нет необходимости.


--- Цитата ---Компилируется так - я и не использую

--- Конец цитаты ---
Что ты используешь? У меня в CodeBlocks не компилировалось, посмотрел мануалы - exit() объявлена в cstdio. Привыкнешь ещё, а потом будешь удивляться почему не компилируется в других средах...


--- Цитата ---Не читал я ещё о enum, посмотрю что он из себя представляет. Через switch идея была сделать.

--- Конец цитаты ---
Это очень просто. enum [имя] {<элемент1>[=значение][, элемент2[=значение2], элемент3[=значение3], ...]} [переменные];
Т.е. enum X {a, b, c}; объявит перечисление X с элементами a, b, c, имеющими значения 0, 1, 2. Далее в коде их можно использовать как константы. Можно сделать так: enum {a = 10, b = 20, c}; - объявление безымянного перечисления, a=10, b=20, c=21.

P.S. Поменьше слушай Mr2, он часто глупости говорит. Или хотя бы обдумывай его слова, а не верь на слово.
А ещё плохо знаком с сабжем, раз осмеивает возможность присвоения объекту самому себе.
Навигация
Главная страница сообщений
Следующая страница
Предыдущая страница

Перейти к полной версии