Инкапсуляция хорошо по интуитивному смыслу дружит с модульностью, поэтому благоразумно давать их вместе — первое как контроль состояния объекта и защита от внешних воздействий, и модульность как уменьшение сложности методом распиливания на независимые части. В рамках первой — это перевод всех данных под private раз и навсегда до конца курса, в рамках второй — разделение класса на пару файлов hpp/cpp и вынесение их в отдельное место, отличное от главной программы, которая уже подключает их через include.
Несмотря на то, что инкапсуляция является стандартной и необходимой практикой в ООП, она вынесена в отдельный детерминированный шаг для того, чтобы: разделить прямой доступ к полям и доступ через методы на уровне написания кода; в первой работе сосредоточиться на абстрагировании, не пытаясь делать много вещей сразу; во второй уже работать с обкатанными понятиями первой л.р. (часть из них должна немного осесть в более долговременную память); сосредоточиться на понимании состояний объекта и его защите.
С точки зрения работы функционал практически не добавляется — только с точки зрения поведения классов необходимо добавить действия по сохранению объекта в корректном состоянии (чтобы Дюймовочка не плыла участки в минус 5 метров, иначе поведение объекта или его состояние может стать некорректным) — это делается как раз вместе с инкапсуляцией. Кроме того, идет разделение и вынос hpp/cpp, что тоже не меняет функционал.
В данной работе сопутствующей темой является оформление кода — по завершению работы код уже должен соответствовать правилам оформления и собрана документация с помощью Doxygen.
Разбиение hpp/cpp является подготовительным шагом к следующей работе, где классы выносятся как отдельная библиотека и там тестируются. Т.е. сначала сплошной cpp с классом и main(), далее main() + файлы hpp/cpp, и далее уже main подключает через svn:externals hpp/cpp. Малые шаги лучше чем все сразу.
Фокус на обязательности инкапсуляции и обязательности всех правил оформления кода.
Класс должен заниматься только тем, что от него требуется — никаких побочных печатей внутри логики. Все печати вне класса.
Сразу прописывыаем защиту от повторной компиляции — чтобы она стояла везде.
Подробности
Разделение реализации и пользователя класса. Это два разных человека, между которыми имеется некоторое соглашение о взаимодействии (интерфейс). Реализация может жить отдельно, выполняя условия интерфейса, пользователь класса может работать с классом, не думая о реализации. Профит — уменьшение сложности и возможность работы людьми независимо друг от друга. Но нужны ресурсы на содержание интерфейса.
Подобное соглашение есть для простых структур данных. По большому счету вы не знаете, как в памяти хранятся int'ы, float'ы и пр. базовые типы. Однако вы знаете, что есть набор операций, которые можно над ними выполнять (интерфейс) и работаете уже оперируя ими, а сами переменные — удобные абстракции соответствующего типа.
Как это делается в C++. Что это дает (защита, разделение).
Типичная сборка проекта в C++ с точки зрения файлов (пары hpp/cpp, которые независимы и подключаемы при необходимости).
Защита от повторного подключения в С++ (как выглядит и зачем).
Доступ к полям класса (public/private/protected). Что такое наследование пока что не знаем, просто помечаем на будущее. Как это выглядит в C++.
Getter'ы и Setter'ы.
Пример изменения реализации — изменяем private и логику функций, однако интерфейс не изменяется.