Menu
Coddy logo textTech

Сокрытие данных

Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy. Урок 36 из 104.

Сокрытие информации выходит за рамки простого использования спецификаторов доступа. Это принцип проектирования, согласно которому вы скрываете не только данные, но и детали того, как ваш class работает внутри.

Цель состоит в том, чтобы предоставить только то, что пользователям вашего class необходимо знать, оставив всё остальное скрытым. Это позволяет изменять внутреннюю реализацию, не затрагивая код, который использует ваш class:

class Temperature {
    double kelvin;    // Внутреннее представление — скрытая деталь
    
public:
    void setCelsius(double c) {
        kelvin = c + 273.15;    // Преобразование скрыто от пользователя
    }
    
    double getCelsius() const {
        return kelvin - 273.15;
    }
    
    double getFahrenheit() const {
        return (kelvin - 273.15) * 9.0/5.0 + 32;
    }
};

Пользователи этого class не знают (и им не нужно знать), что температура внутри хранится в кельвинах. Если позже вы решите хранить её в градусах Цельсия, вам потребуется изменить только внутреннюю implementation — публичный интерфейс останется неизменным.

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

challenge icon

Задание

Легко

Давайте создадим class Distance, демонстрирующий сокрытие информации: расстояния будут внутренне храниться в centimeters, а пользователям будет предоставлен удобный интерфейс для работы с разными единицами измерения. Пользователям вашего class не потребуется знать (или беспокоиться о том), как расстояние хранится internally: они просто будут работать с удобной для них единицей измерения.

Вы создадите два файла, чтобы организовать код:

  • Distance.h: определите class Distance, который скрывает своё внутреннее представление, предоставляя гибкий public-интерфейс. Внутри храните расстояние в centimeters (как double). Это ваша скрытая деталь реализации. Ваш public-интерфейс должен позволять пользователям:
    • Задавать расстояние с помощью setMeters(double m), setCentimeters(double cm) или setKilometers(double km)
    • Получать расстояние с помощью getMeters(), getCentimeters() или getKilometers(): все они должны быть const-методами
    • Складывать два расстояния с помощью add(const Distance& other), который возвращает новый объект Distance

    Включите Default constructor, который initializes расстояние нулём. Логика преобразования должна быть скрыта внутри ваших методов: пользователи просто вызывают setKilometers(5) и getMeters(), не беспокоясь о внутреннем формате хранения.

  • main.cpp: продемонстрируйте, что пользователи могут работать с вашим class, не зная его внутреннего представления. Считайте из input два значения расстояния: first — в метрах, second — в kilometers. Затем:
    • Создайте объект Distance и задайте его, используя значение в метрах
    • Выведите "In meters: <value> m"
    • Выведите "In centimeters: <value> cm"
    • Выведите "In kilometers: <value> km"
    • Создайте второй объект Distance и задайте его, используя значение в kilometers
    • Сложите два расстояния и сохраните результат
    • Выведите "Combined in meters: <value> m"

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

Форматируйте все выходные значения с двумя знаками после запятой, используя std::fixed и std::setprecision(2) из <iomanip>. Преобразуйте input-строки в значения типа double с помощью std::stod().

Справочник преобразований: 1 метр = 100 centimeters, 1 kilometer = 1000 метров.

Попробуйте сами

#include <iostream>
#include <string>
#include <iomanip>
#include "Distance.h"

using namespace std;

int main() {
    // Читаем входные значения
    string metersInput, kmInput;
    cin >> metersInput;  // Первое значение в метрах
    cin >> kmInput;      // Second value in kilometers
    
    // Преобразуем строки в double с помощью std::stod()
    double metersValue = stod(metersInput);
    double kmValue = stod(kmInput);
    
    // Устанавливаем форматирование вывода
    cout << fixed << setprecision(2);
    
    // TODO: Создать первый объект Distance и задать его значением в метрах
    
    // TODO: Вывести "In meters: <value> m"
    
    // TODO: Print "In centimeters: <value> cm"
    
    // TODO: Print "In kilometers: <value> km"
    
    // TODO: Создать второй объект Distance и задать его значением в километрах
    
    // TODO: Сложить два расстояния с помощью метода add()
    
    // TODO: Print "Combined in meters: <value> m"
    
    return 0;
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор C++