Геттеры и сеттеры
Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy — урок 28 из 104.
Когда члены класса являются приватными, внешний код не может получить к ним прямой доступ. Геттеры и сеттеры — это публичные методы, обеспечивающие контролируемый доступ к этим приватным членам: геттеры возвращают значения, а сеттеры их изменяют.
class Temperature {
double celsius; // Приватное поле - нельзя получить доступ напрямую
public:
// Геттер - возвращает значение
double getCelsius() const {
return celsius;
}
// Сеттер - изменяет значение с проверкой
void setCelsius(double value) {
if (value >= -273.15) { // Проверка на абсолютный ноль
celsius = value;
}
}
};Настоящая сила сеттеров заключается в валидации.
Вместо того чтобы разрешать присваивание любого значения, вы можете устанавливать правила. В примере выше значения температуры ниже абсолютного нуля отклоняются. Без сеттера любой мог бы напрямую присвоить некорректные данные.
Геттеры также могут преобразовывать данные перед их возвратом:
class Temperature {
double celsius;
public:
double getCelsius() const { return celsius; }
// Вычисляемый геттер — не хранит значение в фаренгейтах, а вычисляет его
double getFahrenheit() const {
return celsius * 9.0 / 5.0 + 32.0;
}
void setCelsius(double value) { celsius = value; }
};Обратите внимание на ключевое слово const в геттерах — это указывает на то, что они не изменяют объект. Сеттеры не могут быть const, так как их цель — изменять значения членов класса. Этот паттерн использования геттеров и сеттеров является основополагающим для инкапсуляции, предоставляя вам полный контроль над тем, как осуществляется доступ к данным вашего класса и их изменение.
Задание
ЛегкоДавайте создадим систему профилей игроков, которая демонстрирует, как геттеры и сеттеры обеспечивают контролируемый доступ к приватным данным, включая валидацию и вычисляемые свойства.
Вы создадите два файла для организации вашего кода:
Player.h: Определите классPlayer, который управляет профилем игрового персонажа с защищенным доступом к данным. Ваш класс должен иметь:- Приватные члены:
name(string),level(int) иexperience(int) - Конструктор, который принимает имя и инициализирует
levelзначением1, аexperienceзначением0 - Геттер
getName(), который возвращает имя игрока - Геттер
getLevel(), который возвращает текущий уровень - Геттер
getExperience(), который возвращает текущие очки опыта - Сеттер
setName(), который принимает только имена длиной не менее 3 символов — если имя невалидно, оставьте текущее имя без изменений - Сеттер
addExperience(int points), который принимает только положительные значения. Когда опыт достигает или превышает100, уровень игрока повышается: увеличьте уровень на 1 и вычтите 100 из опыта. Это может произойти несколько раз, если добавлено достаточно опыта. - Вычисляемый геттер
getExperienceToNextLevel(), который возвращает количество очков опыта, необходимых для достижения следующего уровня (всегда100 - current experience)
Пометьте все геттеры как
const, так как они не изменяют объект.- Приватные члены:
main.cpp: Продемонстрируйте работу ваших геттеров и сеттеров. Считайте имя игрока и очки опыта для добавления из входных данных (каждое на отдельной строке), затем:- Создайте объект
Playerс введенным именем - Выведите
"Player: <name>, Level: <level>, XP: <experience>" - Добавьте введенные очки опыта с помощью
addExperience() - Снова выведите ту же строку состояния, чтобы показать обновленное состояние
- Выведите
"XP to next level: <amount>" - Попробуйте изменить имя на
"Al"(валидация должна не пройти) - Выведите
"Name after invalid change: <name>" - Измените имя на
"Champion"(должно пройти успешно) - Выведите
"Name after valid change: <name>"
- Создайте объект
Ввод опыта будет предоставлен в виде строки, которую вам нужно будет преобразовать в целое число. Подключите ваш заголовочный файл в main.cpp с помощью #include "Player.h".
Шпаргалка
Геттеры и сеттеры — это публичные методы, которые обеспечивают контролируемый доступ к приватным членам класса.
Базовый паттерн геттера и сеттера:
class Temperature {
double celsius; // Приватный член
public:
// Геттер - возвращает значение (помечен как const)
double getCelsius() const {
return celsius;
}
// Сеттер - изменяет значение
void setCelsius(double value) {
celsius = value;
}
};Сеттеры с валидацией:
void setCelsius(double value) {
if (value >= -273.15) { // Валидация перед установкой
celsius = value;
}
}Вычисляемые геттеры:
// Возвращает вычисленное значение без его сохранения
double getFahrenheit() const {
return celsius * 9.0 / 5.0 + 32.0;
}Ключевые моменты:
- Геттеры должны быть помечены как
const, так как они не изменяют объект - Сеттеры не могут быть
const, так как они изменяют значения членов - Сеттеры позволяют выполнять валидацию для предотвращения некорректных данных
- Геттеры могут преобразовывать или вычислять значения перед их возвратом
Попробуйте сами
#include <iostream>
#include <string>
#include "Player.h"
using namespace std;
int main() {
// Считать имя игрока
string playerName;
getline(cin, playerName);
// Считать очки опыта для добавления (как строку, преобразовать в int)
string expString;
getline(cin, expString);
int expToAdd = stoi(expString);
// TODO: Создать объект Player с введенным именем
// TODO: Вывести начальный статус: "Player: <name>, Level: <level>, XP: <experience>"
// TODO: Добавить введенные очки опыта, используя addExperience()
// TODO: Вывести обновленную строку статуса
// TODO: Вывести "XP to next level: <amount>"
// TODO: Попробовать изменить имя на "Al" (валидация должна не пройти)
// TODO: Вывести "Name after invalid change: <name>"
// TODO: Изменить имя на "Champion" (должно пройти успешно)
// TODO: Вывести "Name after valid change: <name>"
return 0;
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыСборка и компиляция C++Заголовочные файлы и файлы исходного кодаПространства имен и область видимостиВведение в ООП на C++Классы и объектыУказатель 'this'Методы (функции-члены)Атрибуты (члены данных)Основы конструкторов и деструкторовИтоги — Простой калькулятор4Свойства классов
Члены экземпляра против статическихГеттеры и сеттерыКонстантные функции-членыКлючевое слово mutableСтатические методы и переменныеДружественные функции и классыИтоги — Менеджер банковских счетов7Наследование
Основы наследованияУровни доступа при наследованииПорядок вызова конструкторов и деструкторовПереопределение методовВиртуальные функции и VTableМножественное наследованиеВиртуальное наследованиеИтоги — Иерархия сотрудников10Обзор STL
Обзор и философия STLКонтейнеры STLИтераторыАлгоритмы STLФункторы и лямбда-выраженияИтоги: частота слов13Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonFactory и Abstract FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy2Управление памятью
Стек и кучаУказатели и ссылкиДинамическая память (new/delete)Умные указатели в C++RAII в C++Итоги — Менеджер динамического массива5Инкапсуляция
Спецификаторы доступа в C++Спецификаторы доступа: подробный разборСокрытие данныхStruct против ClassВложенные и внутренние классыИтоги — Система учета студентов8Полиморфизм
Полиморфизм компиляции и времени выполненияПерегрузка функцийВиртуальные функции: повторениеЧистые виртуальные функцииАбстрактные классыПроектирование интерфейсов на C++Dynamic Casting и RTTIИтоги: Калькулятор фигур11Продвинутые концепции ООП
Композиция против наследованияМиксины через CRTPИдиома PimplСтирание типовEnum Classes и строгая типизацияОбработка исключений в ООППользовательские иерархии исключений14Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикRAII как паттерн3Конструкторы и деструкторы
Конструктор по умолчаниюПараметризованный конструкторКонструктор копированияКонструктор перемещенияСписки инициализации конструктораДелегирующие конструкторыГлубокое погружение в деструкторыПравило трех / пяти / нуляПовторение — класс String6Перегрузка операторов
Введение в перегрузку операторовПерегрузка арифметических операторовПерегрузка операторов сравненияОператоры потоковПерегрузка оператора присваиванияПерегрузка операторов [] и ()Операторы преобразования типовИтоги — класс Matrix9Шаблоны
Шаблоны функцийШаблоны классовСпециализация шаблоновВариативные шаблоныОсновы SFINAE и Type TraitsИтоги — Обобщенный контейнер