Раздел «Язык Си».ClassWorker:

Указатели. Деструкторы. Статические объекты.

Объекты появляются и исчезают.

Задача про работников.

Три работника собирают яблоки. Каждый работник может собрать несколько яблок за 1 час. Работники работают 8 часов и уходят домой.

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

Решение.

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

Пишем программу:

#include <iostream>
#include <cstdlib>

using namespace std;

// Класс работник. 
class Worker{
  int apple; // количество яблок, которые он собирает в час
public:
// Конструктор по умолчанию. Мы не можем указывать 
// сколько яблок соберет работник. Будет случайное число
     Worker(); 
// Укажем количество яблок при создании рабочего
     Worker(int app);

// Деструктор. (Всегда называется как класс, но перед именем ставится ~)
// Удаляет созданный объект: 
// 1. командой delete
// 2. если объект появился в функции, когда завершается функция
// 3. когда завершается программа
     ~Worker();
// возвращает количество яблок, которые собал работник
     int job();
};
// Конструктор по умолчанию
Worker::Worker(){
// rand() "умеет" вычислять случайное число.
// мы считаем, что больше 100 яблок работник не собирает 
   apple=rand() % 100;
   cout<<"Собираю "<<apple<<" яблок в час"<<endl;
};
// Здесь можно уазать количество яблок
Worker::Worker(int app){
  apple=app;
  cout<<"Собираю "<<apple<<" яблок в час"<<endl;
};
// Деструктор. 
// Обычно работает "деструктор по-умолчанию", так же как и 
// "конструктор по-умолчанию", но можно добавить в деструктор и 
// другие действия 
Worker::~Worker(){
  cout<<"Я ушел домой"<<endl;
};
// работаем
int Worker::job(){
  return apple;
};

int main(){
// Создаем УКАЗАТЕЛИ на трех работников
  Worker *one, *second,*third;
  int basket=0; // корзина для яблок
// Создание работника.
// оператор new создает ДИНАМИЧЕСКИЙ объект,
// использует его конструктор
  one = new Worker();// по-умолчанию

  second = new Worker(25); //инициализируем
  
  third = new Worker();// по-умолчанию

// Рабочий день
  for(int i = 0; i<9; i++){
// Если у нас УКАЗАТЕЛЬ на объект,то 
// для вызова его функций и атрибутов
// используем ->
    basket += one->job();
    cout<<i<<" час: яблок: "<<basket<<endl;
    
    basket += second->job();
    cout<<i<<" час: яблок: "<<basket<<endl;
    
    basket += third->job();
    cout<<i<<" час: яблок: "<<basket<<endl;
  }
// Рабочий день закончился. Все ушли
  delete one; // удаление объекта one
  delete second; // удаление объекта second
  delete third; // удаление объекта third

// Все указатели, которые использовались для
// динамических объектов после удаления
// должны быть равны 0
   one = 0;
   second = 0;
   third = 0;

};

Изменим программу, создадим массив из N работников

// код из программы выше
...
int main(){
// Указатель на будующий массив
  Worker *wrk; 
  int basket=0;// корзина

// ВСЕ ОБЪЕКТЫ, КОТОРЫЕ МОГУТ ЗАНИМАТЬ
// МНОГО ПАМЯТИ (ОДИН ИЛИ НЕСКОЛЬКО)
// ДОЛЖНЫ СОЗДАВАТЬСЯ ДИНАМИЧЕСКИ
   int N = 3; // количество работников
// Создание динамического массива
// из N элементов Worker
  wrk = new Worker[N];
 
  for(int i = 0; i<9; i++){
    basket += wrk[0].job();// первый работает
    cout<<i<<" час: яблок: "<<basket<<endl;
    basket += (wrk+1)->job(); // второй "по указателю"
    cout<<i<<" час: яблок: "<<basket<<endl;
    basket += wrk[2].job();// третий работает
    cout<<i<<" час: яблок: "<<basket<<endl;
  }

// Удаление всего массива.

// ДИНАМИЧЕСКИЕ объекты нужно удалять, чтобы освободить память
// переменные-указатели при этом остаются
 
// Будет работать деструктор 
// КАЖДОГО элемента 

  delete[] wrk;
// Все указатели, которые использовались для
// динамических объектов после удаления
// должны быть равны 0
   wrk = 0;
  
};

Задачи I.

Задача 1.

Отладить и запустить первый пример

Задача 2.

Отладить и запустить второй пример

Задача 3.

Три работника собирают яблоки. Каждый работник может собрать несколько яблок за 1 час. Работники работают 8 часов и уходят домой. К ним прилетают три вороны, которые воруют яблоки. Каждая ворона может украсть несколько яблок (случайное число, но не больше 10) за час. Вороны прилетают в начале рабочего дня и воруют яблоки 16 часов (8 часов после конца рабочего дня). Если яблок в корзине меньше чем может украсть ворона, она крадет все. Если яблок нет - ничего не крадет.

Работников всего n_workers, а ворон - n_crows. Эти чиcла ввести с клавиатуры. Написать программу, которая показывает сколько всего яблок в корзине от начала работы до конца полетов ворон.

// Ворона
class Crow{
  int apple;// украденные яблоки за 1 час
  int *basket;// указатель на корзину с яблоками
public:
// конструктор. Вычисляется случайное количество яблок
   Crow();
// Деструктор. Указатель на корзину должен стать 0
   ~Crow();
// получит указатель на  корзину
   void getBasket(int *pbasket);
// возвращает количество укараденыых яблок
   int steal();

};
//Все функции класса Crow нужно написать и отладить.

// Работник
class Worker{
  int apple; // количество яблок, которые он собирает в час
  int *basket;// указатель на корзину с яблоками
public:
// Конструктор по умолчанию. Мы не можем указывать 
// сколько яблок он  соберет. Будет случайно
     Worker(); 
   
// Деструктор. Указатель на корзину должен стать 0
   ~Worker();
// возвращает количество яблок, которые собал работник
     int job();
    // получит указатель на  корзину
   void getBasket(int *pbasket);
};
//Все функции класса Crow нужно написать и отладить.

int main(){
 // Здесь написать решение задачи.
}

Переменная для корзины должны быть определена в main().

Примечание. Эта программа - самая простая МОДЕЛЬ работы фермы во время сбора урожая.

Глобальные переменные.

Если для Задачи переменную basket описать до описания всех классов, то ее могут "видеть" и использовать функции этих классов.

#include <iostream>
#include <cstdlib>

using namespace std;
// Глобальная переменная
 int basket=0;
// Ворона
class Crow{
  int apple;// украденные яблоки за 1 час
// Указатель на basket не нужен
public:
// конструктор. Вычисляется случайное количество яблок
   Crow();
// Деструктор. Указатель на корзину должен стать 0
   ~Crow();
// получит указатель на  корзину
   void getBasket(int *pbasket);
// возвращает количество укараденыых яблок
   int steal();

};
// Работник
class Worker{
  int apple; // количество яблок, которые он собирает в час
  // Указатель на basket не нужен
public:
// Конструктор по умолчанию. Мы не можем указывать 
// сколько яблок он  соберет. Будет случайное число
     Worker(); 
   
// Деструктор. Указатель на корзину должен стать 0
   ~Worker();
// возвращает количество яблок, которые собал работник
     int job();
    // получит указатель на  корзину
   void getBasket(int *pbasket);
};
// Реализация 
....
void Crow::steal(){
// Ворона "видит" basket
   basket -=apple;
   if (basket < 0) basket = 0;
};
...
// Рабочий "видит" basket
void Worker::job(){
   basket += apple;
};

Задачи II

Задача II.1

Написать программу-модель работы фермы с глобальной переменной.

Переменные static.

Глобальная переменная basket была бы очень удобна, но 1. она объявляется не в классах, и поэтому классы могут ничего о ней "не знать". 2. часто нужно чтобы доступ к ней имели толко объекты этого класса.

Спрячем от ворон basket.

#include <iostream>
#include <cstdlib>

using namespace std;

// Ворона
class Crow{
  int apple;// украденные яблоки за 1 час
// Указатель на basket не нужен
public:
// конструктор. Вычисляется случайное количество яблок
   Crow();
// Деструктор. Указатель на корзину должен стать 0
   ~Crow();
// получит указатель на  корзину
   void getBasket(int *pbasket);
// возвращает количество укараденыых яблок
   int steal();

};
// Работник
class Worker{
  int apple; // количество яблок, которые он собирает в час
// статическая переменная basket. Ее "видят" и могут использовать
// все функции класса. 
// она ОБЩАЯ (одна) для всех объектов класса
// переменная в разделе private "не видна" всем объектам кроме Worker
 static int basket;
public:
// Конструктор по умолчанию. Мы не можем указывать 
// сколько яблок он  соберет. Будет случайно
     Worker(); 
   
// Деструктор. Указатель на корзину должен стать 0
   ~Worker();
// возвращает количество яблок, которые собал работник
     int job();
    // получит указатель на  корзину
   void getBasket(int *pbasket);
};
//Статическая  переменная
// тип или класс переменной (int) полное имя переменной (Worker::basket)  
 int Worker::basket = 0;
// Реализация 
....

// Рабочий "видит" basket
void Worker::job(){
// измениться значение одной общей для всех 
// объектов переменной basket
   basket += apple;
};
...

Задачи III

Задача III.1

Решить задачу "про работников" со статической переменной static int basket в классе Worker. Количество работников вводится с клавиатуры (нужен динамический массив работников)

Задача III.2

#include <iostream>
#include <cstdlib>

using namespace std;

// Ворона
class Crow{
  int apple;// украденные яблоки за 1 час
// Указатель на basket не нужен
public:
// конструктор. Вычисляется случайное количество яблок
   Crow();
// Деструктор. Указатель на корзину должен стать 0
   ~Crow();
// получит указатель на  корзину
   void getBasket(int *pbasket);
// возвращает количество укараденыых яблок
   int steal();

};
// Работник
class Worker{
  int apple; // количество яблок, которые он собирает в час

public:
// Конструктор по умолчанию. Мы не можем указывать 
// сколько яблок он  соберет. Будет случайно
     Worker(); 
   
// Деструктор. Указатель на корзину должен стать 0
   ~Worker();
// возвращает количество яблок, которые собал работник
     int job();
   // статическая переменная basket. Ее "видят" и могут использовать
// все функции класса. 
// она ОБЩАЯ (одна) для всех объектов класса
// переменная в разделе public "видна" всем объектам и функциям
// не только  Worker
  static int basket;
};
//Статическая  переменная
// тип или класс переменной (int) полное имя переменной (Worker::basket)  
 int Worker::basket = 0;
// Реализация 
....

// Рабочий "видит" basket
void Worker::job(){
// измениться значение одной общей для всех 
// объектов переменной basket
   basket += apple;
};
...
int main(){
....
// использование переменной basket 
// только после того как появился 
// хотя бы один объект Worker
   Worker a,b;
   Worker::basket -= 3;
   cout<<Worker::basket<<endl;
};

Перенести переменную static int basket в раздел public класса Worker и решить задачу про ворон. Количество работников N и ворон M вводится с клавиатуры. Нужны динамические массивы и циклы.

-- TatyanaOvsyannikova2011 - 12 Feb 2016