Итоговый проект: каталог и склад
Класс в настоящей программе обычно опирается сразу на несколько идей. Например, он хранит данные в контейнере, принимает текст и проверяет, допустима ли операция. Две задачи итогового проекта устроены так же: новых конструкций в них нет, нужно соединить знакомые.
Две задачи
Каталог хранит книги — структуры Book с номером, названием, автором и отметкой о выдаче. Он находит книги автора, выдаёт книгу по номеру и принимает её обратно. Склад считает, сколько единиц каждого товара на нём лежит. Товаром может быть строка, число или значение другого типа, поэтому склад — шаблон класса (class template).
| Задача | Что понадобится |
|---|---|
| Каталог книг | класс, const-методы, std::vector, std::string и std::string_view |
| Обобщённый склад | шаблон класса, const-метод, std::map |
Если операцию выполнить нельзя — выдать уже выданную книгу или забрать больше, чем есть, — метод возвращает false и ничего не меняет.
Порядок работы
Начните с полей (data members) и метода add: без них остальным методам не с чем работать. Затем пишите по одному методу и после каждого запускайте тесты. Тесты вызывают методы по очереди, и результат вызова зависит от предыдущих вызовов. Поэтому исправляйте первую непройденную проверку: следующие часто не проходят из-за неё.
Как читать проверку
Пройденная проверка ничего не печатает. Непройденная печатает строку со значком ✗ — так заготовка склада отвечает на первую проверку:
✗ fruit.count("apple") == 8 got: -1Слева от == стоит вызов из теста, справа — ожидаемое значение, а после got: — то, что вернул ваш код. Здесь -1 пришло из заготовки: метод count ещё не написан. Под строкой указаны файл с тестами и номер строки, где записана проверка.
У проверки условия, например ✗ fruit.take("apple", 6), части got: нет: условие оказалось ложным, то есть take вернул false. Сводка «Пройдено n из m» показывает, сколько проверок прошло. Если программа остановилась аварийно, строка «Во время проверки» назовёт проверку, на которой это случилось.
Частая ошибка
Цикл по диапазону (range-for) меняет элементы вектора, а переменная цикла объявлена без &:
#include <iostream>
#include <vector>
struct Book {
int id;
bool lent = false;
};
int main() {
std::vector<Book> books{{1}, {2}};
for (Book book : books) { // ✗
book.lent = true;
}
std::cout << books[0].lent << ' ' << books[1].lent << '\n'; // 0 0
}Программа собирается и выводит 0 0: на каждой итерации book — копия элемента, и true получает копия. В каталоге такая ошибка видна по тестам: повторная выдача той же книги снова возвращает true. Объявите переменную цикла ссылкой (reference): for (Book& book : books). Тогда цикл изменит сами элементы, и программа выведет 1 1.