Лабораторная работа №8. Классы в C++

Общие требования

Все создаваемые классы, их поля и функции-члены должны сопровождаться комментариями. Каждый фрагмент кода необходимо проверять в main как можно раньше. Проверки с помощью assert должны идти раньше любого ввода и вывода в main.

Проект «Книжный магазин»

Класс книги book [2 балла]

Создать пустой проект BookShop и добавить в него файл main.cpp с функцией main. Создать заголовочный файл book.h (не забывая о стражах включения), описать в нём пустой класс book, включить этот файл в main.cpp, собрать (build) проект. Добавить в класс book члены, перечисленные ниже.

Подсказка. При работе в Visual Studio для добавления класса удобно воспользоваться меню Проект->Добавить класс, либо навести указатель мыши на "Файлы заголовков", нажать правую кнопку, и в контекстном меню выбрать Добавить->Класс

Напоминание. Все поля должны быть закрытыми — private, причём писать это слово необязательно, так как по умолчанию все члены класса попадают в эту секцию, пока не открыта другая секция. Все функции-члены размещаются в секции public, тела функций-членов определять внутри описания класса, если явно не требуется обратное.

Предостережение. Обратите внимание на ; после }  в определении класса (так же, как и структуры). Её пропуск приводит к очень непонятным ошибкам компилятора!

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

  1. Поля класса book:

    • _title (название книги) типа std::string,
    • _author (автор) типа std::string,
    • _price (цена): неотрицательное число с плавающей точкой двойной точности (double),
    • целочисленное поле _discount (скидка в процентах от 0 до 100).
  2. Конструктор класса book с параметрами, задающими значения всех полей, причём скидка ­— параметр, равный по умолчанию нулю.

    Указание 1. Используйте списки инициализации (про список инициализации либо читаем в Лекции 4, либо здесь).

    Указание 2. Если скидка находится вне промежутка от 0 до 100, должно генерироваться стандартное исключение invalid_argument, объявленное в заголовочном файле stdexcept:

    throw invalid_argument("Incorrect discount");

    Это условие можно проверять только в теле конструктора, так что нет возможности разумно выставить значение discount в списке инициализации, его следует опустить. То же касается и цены: следует проверять её неотрицательность перед инициализацией соответствующего поля.

  3. [1 балл] Константные функции-члены title, author, price и discount, возвращающие значения соответствующих полей.
    Указание. Заголовок константной функции в заголовочном файле выглядит так:

    	string title() const;
    
    Напоминание. Константность функции-члена означает, что в теле этой функции не меняется состояние (значения полей) объекта. Константность обозначается спецификатором const после списка параметров в заголовке функции.

  4. Константная функция-член real_price, вычисляющая цену товара с учётом скидки. Вынесите определение этой функции в соответствующий заголовку cpp-файл (book.cpp).

  5. [1.5 балла] Перегруженная операция вывода книги в поток (реализация в book.h со спецификатором inline):

    ostream & operator<<(ostream & os, book const & b);

    Замечание. В данном случае не требуется делать операцию вывода в поток другом класса, так как в классе имеются функции доступа ко всем полям. (примеры смотрите в электронном конспекте).

  6. Функции, устанавливающие новые значения цены и скидки с именами price и discount (реализация в book.cpp). Помните, что благодаря механизму перегрузки имён функций в C++, допускается наличие двух и более функций с одинаковым именем, но разными списками параметров.

    Указание. Поддерживайте инвариант класса: цена не может быть отрицательной, а скидка может быть от 0 до 100. В случае нарушения генерируйте исключение. Чтобы код проверки и установки значения скидки не дублировался в конструкторе, используйте в теле конструктора вызов функций price и discount.

  7. [2 балла] В функцию main() добавьте демонстрацию работы функций-членов класса book, а также операции вывода в поток. Добавьте в main() следующий код:

    	Book book1("Анна Каренина", "Лев Толстой", 100.0, 25),
    		 book2("Курс дифференциального и интегрального исчисления", "Григорий Фихтенгольц", 200, 33),
    		 book3("Язык программирования С++", "Бьярне Страуструп", 300, 50);
    	cout << book1;
    	cout << book2;
    	cout << book3;
    	cout << endl;
    	book1.setDiscount(10);
    	book2.setPrice(book2.real_price());
    	cout << book1;
    	cout << book2;
    


Класс книжного магазина bookshop [1 балл]

Создать заголовочный файл bookshop.h и описать в нём класс bookshop со следующими полями (закрытыми) и функциями-членами (открытыми).

  1. Поля _name (название магазина, std::string) и _books  (вектор объектов класса book).

  2. Конструктор с одним параметром — названием магазина. (Не забываем про список инициализации.)

  3. Константная функция чтения названия магазина.

  4. Перегруженная операция += для добавления книги в магазин (в виде функции-члена):

    bookshop & operator+=(book const & new_book) { /*...*/ }
  5. Константная функция определения количества книг в магазине.

[3 балла] Продемонстрировать в основной программе использование класса bookshop, использовать assert.

Дополнительные задачи

Создать файл bookshop.cpp и реализовать в нём следующие функции и функции-члены класса bookshop:

  1. Перегруженная операция вывода книжного магазина в поток

    Указание 1. Объявить в .h-файле эту функцию дружественной.

    Указание 2. В реализации воспользоваться операцией << для каждого экземпляра книги в магазине.

  2. Поиск самой дешевой книги в магазине (функция должна возвращать объект класса book).

  3. Установка заданной скидки на все книги магазина.

  4. Продемонстрировать в основной программе использование новых функций класса bookshop.