C.133: Избегайте `protected` данных
Альтернативная формулировка: Сделайте данные члена public или (желательно) private.
Причина
protected данные - это источник сложности и ошибок. protected данные усложняют утверждение инвариантов. protected данные по своей природе нарушают рекомендацию против помещения данных в базовые классы, что обычно приводит к необходимости иметь дело с виртуальным наследованием.
Пример (плохо)
class Shape {
public:
// ... функции интерфейса ...
protected:
// данные для использования в производных классах:
Color fill_color;
Color edge_color;
Style st;
};
Теперь каждому производному Shape предстоит корректно манипулировать защищенными данными. Это было популярно, но также является основным источником проблем обслуживания. В большой иерархии классов согласованное использование защищенных данных сложно поддерживать, поскольку может быть много кода, распределенного по множеству классов. Набор классов, которые могут касаться этих данных, открыт: кто угодно может создать новый класс и начать манипулировать защищенными данными. Часто невозможно изучить полный набор классов, поэтому любое изменение представления класса становится невозможным. Нет принудительного инварианта для защищенных данных; это очень похоже на набор глобальных переменных. Защищенные данные фактически стали глобальными для большого количества кода.
Примечание
Защищенные данные часто выглядят заманчиво для включения произвольных улучшений через наследование. Часто то, что вы получаете, это необоснованные изменения и ошибки. Предпочитайте private данные с четко определенным и принудительным инвариантом. В качестве альтернативы, и часто лучше, держите данные вне любого класса, используемого как интерфейс.
Примечание
Защищенная функция-член может быть просто хороша.
Контроль
Отмечайте классы с protected данными.