Menu
Coddy logo textTech

Struct против Class

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

В C++ struct и class практически идентичны. Оба могут иметь переменные-члены, функции-члены, конструкторы и поддерживать наследование. Единственное различие заключается в их уровне доступа по умолчанию.

В class члены являются private по умолчанию. В struct члены являются public по умолчанию:

struct Point {
    int x;    // открытый по умолчанию
    int y;    // открытый по умолчанию
};

class Circle {
    double radius;    // закрытый по умолчанию
    
public:
    double getRadius() { return radius; }
};

Это также относится к наследованию. struct наследуется публично по умолчанию, в то время как class наследуется приватно:

struct DerivedStruct : Base {};    // публичное наследование
class DerivedClass : Base {};      // закрытое наследование

Помимо этих значений по умолчанию, технической разницы нет. Однако соглашения имеют значение.

Большинство программистов на C++ используют struct для простых контейнеров данных с публичными членами (таких как координаты или конфигурация) и class, когда важны инкапсуляция и поведение. Следование этому соглашению делает намерения вашего кода более понятными для других разработчиков.

challenge icon

Задание

Легко

Давайте создадим простую систему конфигурации, которая демонстрирует, когда использовать struct, а когда class, основываясь на соглашениях C++. Вы создадите struct для простых данных, которые должны быть открыто доступны, и class для данных, требующих инкапсуляции и контролируемого доступа.

Для организации кода вы создадите два файла:

  • Config.h: Определите структуру и класс, представляющие различные типы конфигурационных данных.

    Сначала создайте struct с именем Dimensions — простой контейнер данных для ширины и высоты (оба типа int). Поскольку в структурах члены по умолчанию являются публичными, они должны быть доступны напрямую без геттеров. Добавьте метод area(), который возвращает произведение ширины и высоты.

    Затем создайте class с именем AppConfig, который управляет настройками приложения с надлежащей инкапсуляцией. Он должен хранить название приложения (строка) и объект Dimensions для размера окна. Поскольку члены класса по умолчанию являются приватными, вам нужно будет явно сделать ваш публичный интерфейс доступным. Реализуйте:

    • Конструктор, принимающий название приложения, ширину и высоту
    • Геттер getAppName(), который возвращает название
    • Геттер getWindowSize(), который возвращает Dimensions
    • Метод displayConfig(), который выводит: "App: <name>, Window: <width>x<height>, Area: <area>"
  • main.cpp: Продемонстрируйте разницу между использованием структуры и класса. Считайте название приложения, ширину и высоту из входных данных (три отдельные строки), затем:
    • Создайте структуру Dimensions напрямую со значениями ширины и высоты — обратитесь к её членам напрямую, чтобы вывести: "Direct struct access: <width> x <height>"
    • Создайте объект AppConfig со всеми тремя значениями
    • Вызовите displayConfig(), чтобы показать полную конфигурацию
    • Используйте геттер для получения размеров окна и выведите: "Via getter - Area: <area>"

Эта задача подчеркивает соглашение: используйте struct, когда у вас есть простые, прозрачные данные (например, координаты или размеры), и используйте class, когда вы хотите контролировать доступ и добавить поведение вокруг ваших данных.

Преобразуйте входные данные ширины и высоты из строк в целые числа с помощью std::stoi(). Не забудьте про include guards в заголовочном файле.

Шпаргалка

В C++, struct и class практически идентичны, за одним ключевым исключением: их уровень доступа по умолчанию.

В struct члены являются публичными (public) по умолчанию:

struct Point {
    int x;    // публичный по умолчанию
    int y;    // публичный по умолчанию
};

В class члены являются приватными (private) по умолчанию:

class Circle {
    double radius;    // приватный по умолчанию
    
public:
    double getRadius() { return radius; }
};

Это также относится к наследованию:

struct DerivedStruct : Base {};    // публичное наследование по умолчанию
class DerivedClass : Base {};      // приватное наследование по умолчанию

Соглашение: Используйте struct для простых контейнеров данных с публичными членами, а class — когда важны инкапсуляция и поведение.

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

#include <iostream>
#include <string>
#include "Config.h"

using namespace std;

int main() {
    // Чтение входных данных
    string appName;
    string widthStr;
    string heightStr;
    
    getline(cin, appName);
    getline(cin, widthStr);
    getline(cin, heightStr);
    
    int width = stoi(widthStr);
    int height = stoi(heightStr);
    
    // TODO: Создайте структуру Dimensions с полями width и height
    // Обратитесь к её полям напрямую, чтобы вывести: "Direct struct access: <width> x <height>"
    
    // TODO: Создайте объект AppConfig с параметрами appName, width и height
    
    // TODO: Вызовите метод displayConfig() у объекта AppConfig
    
    // TODO: Используйте геттер getWindowSize(), чтобы получить размеры и вывести: "Via getter - Area: <area>"
    
    return 0;
}
quiz iconПроверьте себя

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

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