Пропадают данные C++

268
17 августа 2017, 22:46

Здравствуйте, мне необходимо создать класс глобального прямоугольника, в котором создаются наследуемые классы прямоугольнички. При создании почему то не создаются, хотя если из класс глобальных прямоугольников убрать конструктор копий и деструктор, то все будет работать. Может кто-нибудь объяснить причину этого? Вот код:

    #include <iostream>
    #include <stdlib.h>
    #include <time.h>
    class GlobalRectangle
    {
    public:
      GlobalRectangle(); // Конструктор
      GlobalRectangle(const GlobalRectangle&); // Констуктор копий
      ~GlobalRectangle(); // Деструктор
      void renderGlobalRectangle(); // Отрисовка прямоугольника
      int getRows() { return mRows; }
      int getColumns() { return mColumns; }
      int getNRectangle() { return mnRectangle; }
      int getGlobalRectangle(int r, int c) { return mGlobalRectangle[r][c]; }
      void setGlobalRectangle(int r, int c, int value) { mGlobalRectangle[r][c] = value; }
      int getRectangleCreated() const { return *mRectangleCreated; }
      void setRectangleCreated(int rectangleNo) { *mRectangleCreated = rectangleNo; }
    protected:
      static const int mRows = 25;
      static const int mColumns = 80;
      int mGlobalRectangle[mRows][mColumns]; // Общий прямоугольник
    private:
      int* mRectangleCreated; // Количество созданных прямоугольничков
      int mnRectangle; // Количество прямоугольничков
      int x, y; //Координаты ячеек
    };
    GlobalRectangle::GlobalRectangle()
    {
      for (int r = 0; r < mRows; r++) // Заполнение прямоугольника единичками
        for (int c = 0; c < mColumns; c++)
          setGlobalRectangle(r, c, 1);
      mnRectangle = rand() % 30 + 15; // Количество прямоугольничков
      mRectangleCreated = new int(0); // Создано прямоугольничков: 0
    }
    GlobalRectangle::GlobalRectangle(const GlobalRectangle& rhs)
    {
      mRectangleCreated = new int;
      *mRectangleCreated = rhs.getRectangleCreated();
    }
    GlobalRectangle::~GlobalRectangle()
    {
      delete mRectangleCreated;
      mRectangleCreated = 0;
    }
    void GlobalRectangle::renderGlobalRectangle() // Отрисовка прямоугольника
    {
      for (int r = 0; r < mRows; r++)
      {
        for (int c = 0; c < mColumns; c++)
          std::cout << getGlobalRectangle(r, c);
        std::cout << std::endl;
      }
    }
    class Rectangle : public GlobalRectangle
    {
    public:
      Rectangle();
      ~Rectangle();
      bool attemptCreateRectangle(GlobalRectangle rectangle); // Попытка создания прямоугольничка
      int getAttempt() const { return mAttempt; }
      void setAttempt(int attempt) { mAttempt = attempt; }
      int getRectangleLength() const { return mRectangleLength; }
      void setRectangleLength(int rectangleLength) { mRectangleLength = rectangleLength; }
      int getRectangleHeight() const { return mRectangleHeight; }
      void setRectangleHeight(int rectangleHeight) { mRectangleHeight = rectangleHeight; }
      int getX() const { return mx; }
      void setX(int x) { mx = x; }
      int getY() const { return my; }
      void setY(int y) { my = y; }
      int getRectangleNo() const { return mRectangleNo; }
      void setRectangleNo(int rectangleNo) { mRectangleNo = rectangleNo; }

      int getMaxLength() const { return mMaxLength; }
      int getMaxHeight() const { return mMaxHeight; }
      int getMaxArea() const { return mMaxArea; }
      int getMaxAttemptCreateRectangle() const { return mMaxAttemptCreateRectangle; }
    private:
      const int mMaxLength = 10; // Максимальная длина прямоугольничка
      const int mMaxHeight = 10; // Максимальная ширина прямоугольничка
      const int mMaxArea = 60; // Максимальная площадь прямоугольничка
      const int mMaxAttemptCreateRectangle = 5; // Попыток создания прямоугольничка
      int mRectangleLength, mRectangleHeight; // Длина и ширина прямоугольничка
      int mx, my; //Координаты ячеек
      int mAttempt = 0; // Попытка
      int mRectangleNo; // Номер прямоугольничка
    };

    Rectangle::Rectangle()
    {
      setRectangleNo(0);
    }
    Rectangle::~Rectangle()
    {
    }
    bool Rectangle::attemptCreateRectangle(GlobalRectangle rectangle) // Попытка создания прямоугольничка
    {
      bool isSuccess = false;
      int rectangleLength, rectangleHeight; // Длина и ширина прямоугольничка
      int x, y; // Координаты ячеек
      int maxLength = getMaxLength(); // Максимальная длина
      int maxHeight = getMaxHeight(); // Максимальная высота
      int maxArea = getMaxArea(); // Максимальная площадь
      setAttempt(mAttempt++); //Увелечение номера попытки
      x = rand() % mRows; // Случайная координата x
      y = rand() % mColumns; // Случайная координата y
      rectangleLength = rand() % maxLength + 3; // Длина прямоугольничка
      rectangleHeight = rand() % maxHeight + 3; // Ширина прямоугольничка
                            // Проверка максимальной площади
      if ((rectangleLength * rectangleHeight) > maxArea)
        return isSuccess;
      // Проверка умещается прямоугольничек в общем прямоугольнике или нет
      if (((x + rectangleLength) > mRows) || ((y + rectangleHeight) > mColumns))
        return isSuccess;
      // Проверка не мешается ли прямоугольничек другим прямоугольничкам
      for (int r = x - 1; r < x + rectangleLength + 1; r++)
        for (int c = y - 1; c < y + rectangleHeight + 1; c++)
        {
          int value = rectangle.getGlobalRectangle(r, c);
          if (value == 0)
            return isSuccess;
        }
      setRectangleLength(rectangleLength);
      setRectangleHeight(rectangleHeight);
      setX(x);
      setY(y);
      setAttempt(0); // Сброс количества попыток
      int rectangleNo = rectangle.getRectangleCreated() + 1; // Присвоение номера прямоугольничка
      rectangle.setRectangleCreated(rectangleNo); // Увеличение количества прямоугольничков
      setRectangleNo(rectangleNo);
      isSuccess = true;
      return isSuccess;
    }
    int main()
    {
      GlobalRectangle globalRectangle;
      int nRectangle = globalRectangle.getNRectangle(); // Количество создаваемых прямоугольничков
      std::cout << "nRectangle: " << nRectangle << std::endl;
      // Выделяется память для объектов класса Rectangle в количестве nRectangle
      Rectangle *rectangleNo = new Rectangle[nRectangle];
      for (int i = 0; i < nRectangle; i++)
      {
        int maxAttempt = rectangleNo[i].getMaxAttemptCreateRectangle();
        int attempt = rectangleNo[i].getAttempt();
        for (int a = 0; a < maxAttempt; a++)
        {
          bool isSuccess = rectangleNo[i].attemptCreateRectangle(globalRectangle);
          if (isSuccess == true)
          {
            int x = rectangleNo[i].getX();
            int y = rectangleNo[i].getY();
            int rectangleLength = rectangleNo[i].getRectangleLength();
            int rectangleHeight = rectangleNo[i].getRectangleHeight();
            for (int r = x; r < x + rectangleLength; r++)               // Создание прямоугольничка
              for (int c = y; c < y + rectangleHeight; c++)
                globalRectangle.setGlobalRectangle(r, c, 0);
            break;
          }
        }
      }

      globalRectangle.renderGlobalRectangle();
      int rectangleCreated = globalRectangle.getRectangleCreated();
      std::cout << "Rectangle Created: " << rectangleCreated << std::endl;
      for (int i = 0; i < nRectangle; ++i)
      {
        std::cout << "rectangleNo[" << i << "]: " << rectangleNo[i].getRectangleNo() << std::endl;
      }
      delete[] rectangleNo;
      char response;
      std::cin >> response;
      return 0;
    }

Вывод с консоли:

nRectangle: 26
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
Rectangle Created: 0
rectangleNo[0]: 0
rectangleNo[1]: 0
rectangleNo[2]: 0
rectangleNo[3]: 0
rectangleNo[4]: 0
rectangleNo[5]: 0
rectangleNo[6]: 0
rectangleNo[7]: 0
rectangleNo[8]: 0
rectangleNo[9]: 0
rectangleNo[10]: 0
rectangleNo[11]: 0
rectangleNo[12]: 0
rectangleNo[13]: 0
rectangleNo[14]: 0
rectangleNo[15]: 0
rectangleNo[16]: 0
rectangleNo[17]: 0
rectangleNo[18]: 0
rectangleNo[19]: 0
rectangleNo[20]: 0
rectangleNo[21]: 0
rectangleNo[22]: 0
rectangleNo[23]: 0
rectangleNo[24]: 0
rectangleNo[25]: 0
Answer 1

Начнём копать отсюда:

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

Вопрос первый: где вообще единственному экземпляру GlobalRectangle может потребоваться копирующий конструктор?

Ответ находится в попытке создания вложенного прямоугольника:

bool Rectangle::attemptCreateRectangle(GlobalRectangle rectangle) {
    ...
    int rectangleNo = rectangle.getRectangleCreated() + 1; // Присвоение номера прямоугольничка
    rectangle.setRectangleCreated(rectangleNo); // Увеличение количества прямоугольничков
    ...
}

В свою очередь,

void setRectangleCreated(int rectangleNo) { *mRectangleCreated = rectangleNo; }

запишет в указатель на число созданных прямоугольников новое значение.

У меня сладывается ощущение, что вргументом должна быть ссылка на общий прямоугольник, а не копия, но продолжу.

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

Однако злить старшего разрабочика не стоит; поставим конструктор на место и вернёмся ко второму вопросу: а что же, собственно, не работает?

Вызов в main:

rectangleNo[i].attemptCreateRectangle(globalRectangle);

передаёт globalRectangle по значению - т.е. делает копию, и, в силу правильно(!) написанного копирующего конструктора, этот вызов не меняет состояние оригинала. Поэтому ближе к концу

int rectangleCreated = globalRectangle.getRectangleCreated();

возвращает 0, т.к. оригинал не в курсе, что в его копиях создавались прямоугольники.

READ ALSO
Вызов метода JWS с помощью jQuery

Вызов метода JWS с помощью jQuery

Есть веб-сервис SubtractionServicejws:

231
Как совместить click mouseover mouseout

Как совместить click mouseover mouseout

Есть меню, в меню несколько пунктов, как сделать так чтобы при клике на какой-то из них, background менял цвет(допустимсерый), и оставался серым...

306
Несколько номеров в строке

Несколько номеров в строке

Есть такой плагин Masked Input Plugin

221
inputMask hh:mm:ss alias

inputMask hh:mm:ss alias

Здравствуйте! Подключаю inputMask с алиасом hh:mm:ss если ввел к примеру 12:10:20, ставлю курсор на часы и удаляю символы - очищается только ячейка часовА...

229