Struct против Class
Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy. Урок 37 из 104.
В C++, struct и class почти идентичны. Both могут иметь переменные-члены, функции-члены, constructor и поддерживают inheritance. Единственное различие — их уровень доступа по умолчанию.
В class члены по умолчанию являются закрытыми. В struct члены по умолчанию являются открытыми:
struct Point {
int x; // public по умолчанию
int y; // public по умолчанию
};
class Circle {
double radius; // private по умолчанию
public:
double getRadius() { return radius; }
};Это также относится к inheritance. struct наследует публично по умолчанию, тогда как class наследует приватно:
struct DerivedStruct : Base {}; // публичное наследование
class DerivedClass : Base {}; // приватное наследованиеПомимо этих значений по умолчанию, технических различий нет. Однако соглашения имеют значение.
Большинство программистов на C++ используют struct для простых контейнеров данных с общедоступными членами (например, для координаты или конфигурации), а class — когда важны инкапсуляция и поведение. Следование этому соглашению помогает другим разработчикам лучше понимать назначение вашего кода.
Задание
ЛегкоДавайте создадим простую систему конфигурации, которая демонстрирует, когда следует использовать struct и когда class, исходя из соглашений C++. Вы создадите struct для простых данных, которые должны быть открыто доступны, и class для данных, которым нужны инкапсуляция и контролируемый access.
Вы создадите два файла, чтобы организовать свой код:
Config.h: Define и struct, и class, представляющие разные виды данных конфигурации.Сначала создайте
structс именемDimensions: простой контейнер данных для ширины и высоты (обе имеют типint). Поскольку у struct по умолчанию есть public-члены, к ним следует обращаться directly, без getter-ов. Include методarea(), который возвращает произведение ширины и высоты.Затем создайте
classс именемAppConfig, который управляет настройками приложения с proper инкапсуляцией. Он должен хранить имя приложения (строку) и объектDimensionsдля размера окна. Поскольку члены class по умолчанию являются private, вам потребуется явно сделать свой public interface доступным. Предоставьте:- Constructor, принимающий имя приложения, ширину и высоту
- getter
getAppName(), возвращающий имя - getter
getWindowSize(), возвращающийDimensions - Метод
displayConfig(), который выводит:"App: <name>, Window: <width>x<height>, Area: <area>"
main.cpp: Продемонстрируйте разницу между использованием struct и class. Считайте из input имя приложения, ширину и высоту (три отдельные строки), затем:- Создайте struct
Dimensionsdirectly, используя значения ширины и высоты: обратитесь к его членам directly, чтобы вывести:"Direct struct access: <width> x <height>" - Создайте объект
AppConfigсо всеми тремя значениями - Вызовите
displayConfig(), чтобы показать полную конфигурацию - Используйте getter, чтобы получить размеры окна, и выведите:
"Via getter - Area: <area>"
- Создайте struct
Эта задача демонстрирует соглашение: используйте struct, когда у вас есть простые прозрачные данные (например, координаты или размеры), и используйте class, когда вы хотите контролировать access и добавлять поведение к своим данным.
Преобразуйте входные значения ширины и высоты из строк в целые числа с помощью std::stoi(). Не забудьте добавить header guards в файл заголовка.
Попробуйте сами
#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
// Access its members directly to print: "Direct struct access: <width> x <height>"
// TODO: Создайте объект AppConfig с appName, width и height
// TODO: Вызовите displayConfig() у объекта AppConfig
// TODO: Use getWindowSize() getter to get dimensions and print: "Via getter - Area: <area>"
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Итоги — Обобщенный контейнерПотренируйтесь самостоятельно: Онлайн-компилятор C++