Указатели. Деструкторы. Статические объекты.
Объекты появляются и исчезают.
Задача про работников.
Три работника собирают яблоки. Каждый работник может собрать несколько яблок за 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