Программирование классы и методы

Содержание:

Класс — это элемент ПО, описывающий абстрактный тип данных и его частичную или полную реализацию. Другие абстрактные типы данных — метаклассы, интерфейсы, структуры, перечисления, — характеризуются какими-то своими, другими особенностями. Наряду с понятием «объекта» класс является ключевым понятием в ООП (хотя существуют и бесклассовые объектно-ориентированные языки, например, Self, Lua; подробнее смотрите Прототипное программирование). Суть отличия классов от других абстрактных типов данных состоит в том, что при задании типа данных класс определяет одновременно как интерфейс, так и реализацию для всех своих экземпляров, а вызов метода-конструктора обязателен. Точный смысл этой фразы будет раскрыт ниже.

На практике объектно-ориентированное программирование сводится к созданию некоторого количества классов, включая интерфейс и реализацию, и последующему их использованию. Графическое представление некоторого количества классов и связей между ними называется диаграммой классов. Объектно-ориентированный подход за время своего развития накопил множество рекомендаций (паттернов) по созданию классов и иерархий классов.

Идея классов пришла из работ по базам знаний, имеющих отношение к исследованиям по искусственному интеллекту. Используемые человеком классификации в зоологии, ботанике, химии, деталях машин, несут в себе основную идею, что любую вещь всегда можно представить частным случаем некоторого более общего понятия. Конкретное яблоко — это в целом некоторое яблоко, вообще яблоко, а любое вообще яблоко — фрукт. (Яблоки и груши — частый пример классов в учебных пособиях по объектно-ориентированному программированию.)

Везде далее слова «класс», «объект», «интерфейс» и «структура» будут употребляться в своих специальных значениях, заданных в рамках ООП.

Содержание

Классы и объекты, понятие экземпляра класса, понятие членов класса [ править | править код ]

В объектно-ориентированной программе с применением классов каждый объект является «экземпляром» некоторого конкретного класса, и других объектов не предусмотрено. То есть «экземпляр класса» в данном случае означает не «пример некоторого класса» или «отдельно взятый класс», а «объект, типом которого является какой-то класс». При этом в разных языках программирования допускается либо не допускается существование еще каких-то типов данных, экземпляры которых не являются объектами (то есть язык определяет, являются ли объектами такие вещи, как числа, массивы и указатели, или не являются, и, соответственно, есть ли такие классы как «число», «массив» или «указатель», экземплярами которых были бы каждое конкретное число, массив или указатель).

Например, абстрактный тип данных «строка текста» может быть оформлен в виде класса, и тогда все строки текста в программе будут являться объектами — экземплярами класса «строка текста».

При использовании классов все элементы кода программы, такие как переменные, константы, методы, процедуры и функции, могут принадлежать (а во многих языках обязаны принадлежать) тому или иному классу. Сам класс в итоге определяется как список своих членов, а именно полей (свойств) и методов/функций/процедур. В зависимости от языка программирования к этому списку могут добавиться константы, атрибуты и внешние определения.

Как и структуры, классы могут задавать поля — то есть переменные, принадлежащие либо непосредственно самому классу (статические), либо экземплярам класса (обычные). Статические поля существуют в одном экземпляре на всю программу (или, в более сложном варианте, — в одном экземпляре на процесс или на поток/нить). Обычные поля создаются по одной копии для каждого конкретного объекта — экземпляра класса. Например, общее количество строк текста, созданных в программе за время её работы, будет являться статическим полем класса «строка текста». А конкретный массив символов строки будет являться обычным полем экземпляра класса «строка текста», так же как переменная «фамилия», имеющая тип «строка текста», будет являться обычным полем каждого конкретного экземпляра класса «человек».

В ООП при использовании классов весь исполняемый код программы (алгоритмы) будет оформляться в виде так называемых «методов», «функций» или «процедур», что соответствует обычному структурному программированию, однако теперь они могут (а во многих языках обязаны) принадлежать тому или иному классу. Например, по возможности, класс «строка текста» будет содержать все основные методы/функции/процедуры, предназначенные для работы со строкой текста, такие как поиск в строке, вырезание части строки и т. д.

Как и поля, код в виде методов/функций/процедур, принадлежащих классу, может быть отнесен либо к самому классу, либо к экземплярам класса. Метод, принадлежащий классу и соотнесенный с классом (статический метод) может быть вызван сам по себе и имеет доступ к статическим переменным класса. Метод, соотнесенный с экземпляром класса (обычный метод), может быть вызван только у самого объекта, и имеет доступ как к статическим полям класса, так и к обычным полям конкретного объекта (при вызове этот объект передастся скрытым параметром метода). Например, общее количество созданных строк можно узнать из любого места программы, но длину конкретной строки можно узнать только указав, тем или иным образом, длину какой строки будем мерить.

Интерфейс и реализация, наследование реализации [ править | править код ]

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

Программные интерфейсы, а также классы, могут расширяться путём наследования, которое является одним из важных средств повторного использования готового кода в ООП. Наследованный класс или интерфейс будет содержать в себе всё, что указано для всех его родительских классов (в зависимости от языка программирования и платформы, их может быть от нуля до бесконечности). Например, можно создать свой вариант текстовой строки путём наследования класса «моя строка текста» от уже существующего класса «строка текста», при этом предполагается, что программисту не придется заново переписывать алгоритмы поиска и прочее, так как они автоматически будут унаследованы от готового класса, и любой экземпляр класса «моя строка текста» может быть передан не только в готовые методы родительского класса «строка текста» для проведения нужных вычислений, но и вообще в любой алгоритм, способный работать с объектами типа «строка текста», так как экземпляры обоих классов совместимы по программным интерфейсам.

Читайте также:  Как подобрать цвет волос к лицу тест

Класс позволяет задать не только программный интерфейс к самому себе и к своим экземплярам, но и в явном виде написать код, ответственный за вычисления. Если при создании своего нового типа данных наследовать интерфейс, то мы получим возможность передавать экземпляр своего типа данных в любой алгоритм, который умеет работать с этим интерфейсом. Однако нам придется самим написать реализацию интерфейса, то есть те алгоритмы, которыми будет пользоваться интересующий нас алгоритм для проведения вычислений с использованием нашего экземпляра. В то же время, наследуя класс, мы автоматически наследуем готовый код под интерфейс (это не всегда так, родительский класс может требовать реализации каких-то алгоритмов в дочернем классе в обязательном порядке). В этой возможности наследовать готовый код и проявляется то, что в объектно-ориентированной программе тип данных класс определяет одновременно и интерфейс, и реализацию для всех своих экземпляров.

Состояние объекта, понятие областей доступа, конструкторы [ править | править код ]

Одной из проблем структурного программирования, с которой борется ООП, является проблема поддержания правильного значения переменных программы. Часто разные переменные программы хранят логически связанные значения, и за поддержание этой логической связности несет ответственность программист, то есть автоматически связность не поддерживается. Примером могут служить флажки «уволен» и «ожидает премии по итогам года», когда по правилам отдела кадров человек может быть одновременно не уволенным и не ожидающим премии, не уволенным и ожидающим премии, уволенным и не ожидающим премии, но не может быть одновременно и уволенным, и ожидающим премии. То есть любая часть программы, которая проставляет флажок «уволен», всегда должна снимать флажок «ожидает премии по итогам года».

Хороший способ решить эту проблему — объявить флажок «уволен» недоступным к изменению для всех участков программы, кроме одного специально оговоренного. В этом специально оговоренном участке всё будет написано один раз и правильно, а все остальные должны будут обращаться к этому участку всегда, когда они хотят установить или снять флажок «уволен».

В объектно-ориентированной программе флажок «уволен» будет объявлен приватным членом некоторого класса, а для чтения и изменения его будут написаны соответствующие публичные методы. Правила, определяющие возможность или невозможность напрямую изменять какие-либо переменные, называются правилами задания областей доступа. Слова «приватный» и «публичный» в данном случае являются так называемыми «модификаторами доступа». Они называются модификаторами потому, что в некоторых языках они используются для изменения ранее установленных прав при наследовании класса. Совместно классы и модификаторы доступа задают область доступа, то есть у каждого участка кода, в зависимости от того, какому классу он принадлежит, будет своя область доступа относительно тех или иных элементов (членов) своего класса и других классов, включая переменные, методы, функции, константы и т. д. Существует основное правило: ничто в одном классе не может видеть приватных элементов другого класса. Относительно других, более сложных правил, в различных языках существуют другие модификаторы доступа и правила их взаимодействия с классами.

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

  • private (закрытый, внутренний член класса) — обращения к члену допускаются только из методов того класса, в котором этот член определён. Любые наследники класса уже не смогут получить доступ к этому члену. Наследование по типу private делает все члены родительского класса (в том числе public и protected) private-членами класса-наследника (С++);
  • protected (защищённый, внутренний член иерархии классов) — обращения к члену допускаются из методов того класса, в котором этот член определён, а также из любых методов его классов-наследников. Наследование по типу protected делает все public-члены родительского класса protected-членами класса-наследника (С++);
  • public (открытый член класса) — обращения к члену допускаются из любого кода. Наследование по типу public не меняет модификаторов родительского класса (С++);

Проблема поддержания правильного состояния переменных актуальна и для самого первого момента выставления начальных значений. Для этого в классах предусмотрены специальные методы/функции, называемые конструкторами. Ни один объект (экземпляр класса) не может быть создан иначе, как путём вызова на исполнение кода конструктора, который вернет вызывающей стороне созданный и правильно заполненный экземпляр класса. Во многих языках программирования тип данных «структура», как и класс, может содержать переменные и методы, но экземпляры структур, оставаясь просто размеченным участком оперативной памяти, могут создаваться в обход конструкторов, что запрещено для экземпляров классов (за исключением специальных исключительных методов обхода всех подобных правил ООП, предусмотренных в некоторых языках и платформах). В этом проявляется отличие классов от других типов данных — вызов конструктора обязателен.

Практический подход [ править | править код ]

В современных объектно-ориентированных языках программирования (в том числе в php, Java, C++, Oberon, Python, Ruby, Smalltalk, Object Pascal) создание класса сводится к написанию некоторой структуры, содержащей набор полей и методов (среди последних особую роль играют конструкторы, деструкторы, финализаторы). Практически класс может пониматься как некий шаблон, по которому создаются объекты — экземпляры данного класса. Все экземпляры одного класса созданы по одному шаблону, поэтому имеют один и тот же набор полей и методов.

Отношения между классами [ править | править код ]

  • Наследование (Генерализация) — объекты дочернего класса наследуют все свойства родительского класса.
  • Ассоциация — объекты классов вступают во взаимодействие между собой.
  • Агрегация — объекты одного класса входят в объекты другого.
  • Композиция — объекты одного класса входят в объекты другого и зависят друг от друга по времени жизни.
  • Класс-Метакласс — отношение, при котором экземплярами одного класса являются другие классы.

Виды классов [ править | править код ]

Область видимости [ править | править код ]

Область видимости членов класса (то есть область кода, из которой к ним можно обращаться по неквалифицированному имени — без указания имени класса или объекта) не зависит от их области доступа, и всегда совпадает с кодом методов класса.

Область видимости самого класса по-разному определяется в разных языках программирования. В одних языках (таких как Delphi) все классы имеют глобальную видимость (с учётом видимости модуля), в других (таких как Java) область видимости класса связана с содержащей его единицей компиляции (в Java — с пакетом), в третьих (таких как C++ и C#) область видимости класса определяется пространствами имён (namespaces), которые задаются программистом явно и могут совпадать или не совпадать с единицами компиляции.

Классы в языке Object Pascal (среда Delphi) [ править | править код ]

На языке Delphi класс описывается следующим образом:

  • TMyClass — имя класса;
  • class — ключевое слово, начинающее определение класса (в старых версиях также было ключевое слово object );
  • TObject — класс-предок, если есть наследование;
  • private, protected, public, published — ключевые слова, определяющие иерархический доступ к полям и методам в виде обозначения секций областей доступа.

Создается экземпляр (объект) класса так:

Классы в языке C++ [ править | править код ]

Класс в языке C++ создаётся следующим образом:

После своего создания класс считается полноценным типом данных и, следовательно экземпляры класса создаются следующим образом:

Читайте также:  Зарядка лягушка принцип работы

Обращение к членам класса:

Уничтожается экземпляр класса, как и любая переменная, только в случае, если функция, в которой он был создан, завершила работу или если была принудительно освобождена динамическая память, выделенная под класс.

Классы в языке C# [ править | править код ]

Классы в языке C# определяются следующим образом:

В отличие от C++ модификаторы доступа должны указываться для каждого члена в отдельности. Анонимные классы можно определить в методе, например, так:

Классы в языке Ruby [ править | править код ]

Классы в языке Ruby определяются следующим образом:

Создание экземпляра класса:

Уничтожение экземпляра класса не требуется: оно происходит автоматически с помощью «сборщика мусора», как только из памяти исчезет последняя ссылка на него.

Классы в языке Python [ править | править код ]

Определение класса на языке Python с помощью оператора class :

Создание экземпляра класса:

Уничтожение экземпляра класса в явном виде не требуется, так как в Python присутствует автоматический «сборщик мусора». Однако в явном виде удалить ссылку на объект (экземпляр класса или сам класс) можно так:

Классы в языке JavaScript [ править | править код ]

Определение класса на языке JavaScript с помощью оператора class :

Создание экземпляра класса:

Уничтожение экземпляра класса не требуется: оно происходит автоматически с помощью «сборщика мусора», как только из памяти исчезнет последняя ссылка на него.

Классы в языке Java [ править | править код ]

Определение класса на языке Java с помощью оператора class :

Создание экземпляра класса:

Уничтожение экземпляра класса происходит с помощью «сборщика мусора» автоматически.

Весь реальный мир состоит из объектов. Города состоят из районов, в каждом районе есть свои названия улиц, на каждой улице находятся жилые дома, которые также состоят из объектов.

Практически любой материальный предмет можно представить в виде совокупности объектов, из которых он состоит. Допустим, что нам нужно написать программу для учета успеваемости студентов. Можно представить группу студентов, как класс языка C++. Назовем его Students .

Основные понятия

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

У каждого студента есть имя — name и фамилия last_name . Также, у него есть промежуточные оценки за весь семестр. Эти оценки мы будем записывать в целочисленный массив из пяти элементов. После того, как все пять оценок будут проставлены, определим средний балл успеваемости студента за весь семестр — свойство average_ball .

Методы — это функции, которые могут выполнять какие-либо действия над данными (свойствами) класса. Добавим в наш класс функцию calculate_average_ball() , которая будет определять средний балл успеваемости ученика.

  • Методы класса — это его функции.
  • Свойства класса — его переменные.

Функция calculate_average_ball() просто делит сумму всех промежуточных оценок на их количество.

Модификаторы доступа public и private

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

Закрытые данные класса размещаются после модификатора доступа private . Если отсутствует модификатор public , то все функции и переменные, по умолчанию являются закрытыми (как в первом примере).

Обычно, приватными делают все свойства класса, а публичными — его методы. Все действия с закрытыми свойствами класса реализуются через его методы. Рассмотрим следующий код.

Мы не можем напрямую обращаться к закрытым данными класса. Работать с этими данными можно только посредством методов этого класса. В примере выше, мы используем функцию get_average_ball() для получения средней оценки студента, и set_average_ball() для выставления этой оценки.

Функция set_average_ball() принимает средний балл в качестве параметра и присваивает его значение закрытой переменной average_ball . Функция get_average_ball() просто возвращает значение этой переменной.

Программа учета успеваемости студентов

Создадим программу, которая будет заниматься учетом успеваемости студентов в группе. Создайте заголовочный файл students.h, в котором будет находиться класс Students .

Мы добавили в наш класс новые методы, а также сделали приватными все его свойства. Функция set_name() сохраняет имя студента в переменной name , а get_name() возвращает значение этой переменной. Принцип работы функций set_last_name() и get_last_name() аналогичен.

Функция set_scores() принимает массив с промежуточными оценками и сохраняет их в приватную переменную int scores[5] .

Теперь создайте файл main.cpp со следующим содержимым.

В самом начале программы создается объект класса Students . Дело в том, что сам класс является только описанием его объекта. Класс Students является описанием любого из студентов, у которого есть имя, фамилия и возможность получения оценок.

Объект класса Students характеризует конкретного студента. Если мы захотим выставить оценки всем ученикам в группе, то будем создавать новый объект для каждого из них. Использование классов очень хорошо подходит для описания объектов реального мира.

После создания объекта student , мы вводим с клавиатуры фамилию, имя и промежуточные оценки для конкретного ученика. Пускай это будет Вася Пупкин, у которого есть пять оценок за семестр — две тройки, две четверки и одна пятерка.

Введенные данные мы передаем set-функциям, которые присваивают их закрытым переменным класса. После того, как были введены промежуточные оценки, мы высчитываем средний балл на основе этих оценок, а затем сохраняем это значение в закрытом свойстве average_ball , с помощью функции set_average_ball() .

Скомпилируйте и запустите программу.

Отделение данных от логики

Вынесем реализацию всех методов класса в отдельный файл students.cpp.

А в заголовочном файле students.h оставим только прототипы этих методов.

Такой подход называется абстракцией данных — одного из фундаментальных принципов объектно-ориентированного программирования. К примеру, если кто-то другой захочет использовать наш класс в своем коде, ему не обязательно знать, как именно высчитывается средний балл. Он просто будет использовать функцию calculate_average_ball() из второго примера, не вникая в алгоритм ее работы.

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

В начале обучения мы говорили о пространствах имен (namespaces). Каждый класс в C++ использует свое пространство имен. Это сделано для того, чтобы избежать конфликтов при именовании переменных и функций. В файле students.cpp мы используем оператор принадлежности :: перед именем каждой функции. Это делается для того, чтобы указать компилятору, что эти функции принадлежат классу Students .

Создание объекта через указатель

При создании объекта, лучше не копировать память для него, а выделять ее в в куче с помощью указателя. И освобождать ее после того, как мы закончили работу с объектом. Реализуем это в нашей программе, немного изменив содержимое файла main.cpp.

При создании статического объекта, для доступа к его методам и свойствам, используют операция прямого обращения — « . » (символ точки). Если же память для объекта выделяется посредством указателя, то для доступа к его методам и свойствам используется оператор косвенного обращения — « -> ».

Читайте также:  Как найти сумму решений неравенства

Конструктор и деструктор класса

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

Мы можем исправить двойки, если ученик будет хорошо себя вести, и вовремя сдавать домашние задания. А на «нет» и суда нет 🙂

Деструктор класса вызывается при уничтожении объекта. Имя деструктора аналогично имени конструктора, только в начале ставится знак тильды

Обновл. 9 Июн 2019 |

Хотя C++ предоставляет ряд фундаментальных типов данных (например: char, int, long, float, double и т.д.), которых бывает достаточно для решения относительно простых проблем, для решения сложных проблем функционала этих простых типов может не хватать.

Классы

Одной из наиболее полезных фич языка C++ является возможность определять собственные типы данных, которые будут лучше соответствовать в решении конкретных проблем. Вы уже видели, как перечисления и структуры могут использоваться для создания собственных пользовательских типов данных. Например, структура для хранения даты:

Перечисления и структуры — это традиционный (не объектно-ориентированный) мир программирования, в котором мы можем только хранить данные. В C++11 мы можем создать и инициализировать структуру следующим образом:

Для вывода даты на экран (что может понадобиться выполнить и не раз, и не два) хорошей идеей будет написать отдельную функцию. Например:

Результат выполнения программы выше:

В мире объектно-ориентированного программирования типы данных могут не только содержать данные, но и функции, которые будут работать с этими данными. Для определения такого типа данных в C++ используется ключевое слово class. Использование ключевого слова class определяет новый пользовательский тип данных — класс.

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

Единственным существенным отличием здесь является public ключевое слово в классе. О нём мы поговорим детальнее в следующем уроке.

Так же, как объявление структуры, так же и объявление класса не приводит к выделению какой-либо памяти. Для использования класса нужно объявить переменную этого типа класса:

В C++ переменная класса называется экземпляром или объектом класса. Точно так же, как определение переменной фундаментального типа данных (например, int x ) приводит к выделению памяти для этой переменной, так же и создание объекта класса (например, DateClass today ) приводит к выделению памяти для этого объекта.

Методы классов

Помимо хранения данных, классы также могут содержать и функции! Функции, определённые внутри класса, называются функциями-членами или методами. Методы могут быть определены внутри или вне класса. Пока что мы будем определять их внутри класса (для простоты), как определить их вне класса — рассмотрим несколько позже.

Класс Date с методом вывода даты:

Точно так же, как к членам структуры, так и к членам (переменным и функциям) класса доступ осуществляется через оператор выбора членов (.):

Результат выполнения программы выше:

Обратите внимание, как эта программа похожа на программу выше (где используется структура).

Однако есть несколько отличий. В версии DateStruct для print() нам нужно было передать переменную структуры непосредственно в функцию print() в качестве параметра. Если бы мы этого не сделали, то print() не знал бы, какую переменную DateStruct выводить. Нам тогда бы пришлось явно ссылаться на члены структуры внутри функции.

Методы класса работают несколько иначе: все вызовы функций-членов должны быть связаны с объектом класса. Когда мы вызываем today.print() , мы сообщаем компилятору вызвать метод print() объекта today .

Рассмотрим определение метода print() ещё раз:

На что фактически ссылаются m_day , m_month и m_year ? Они ссылаются на связанный объект today (который определён caller-ом).

Поэтому, при вызове today.print() , компилятор интерпретирует:

m_day как today.m_day ;

m_month как today.m_month ;

m_year как today.m_year .

Если бы мы вызвали tomorrow.print() , то m_day ссылался бы на tomorrow.m_day .

По сути, связанный объект неявно передаётся функции-члену. По этой причине его часто называют неявным объектом.

Детальнее о том, как передаётся неявный объект функции-члену, мы поговорим в следующих уроках. Ключевым моментом здесь является то, что для работы с функциями, не являющимися членами класса, нам нужно передавать данные в эту функцию явно (в качестве параметров). А для работы с методами у нас всегда есть неявный объект класса!

Использование префикса m_ (англ. «m» = «members») для переменных-членов помогает различать переменные-члены от параметров функции или локальных переменных внутри методов класса. Это полезно по нескольким причинам:

Во-первых, когда мы видим переменную с префиксом m_ , то мы понимаем, что работаем с переменной-членом класса.

Во-вторых, в отличие от параметров функции или локальных переменных, объявленных внутри функции, переменные-члены объявляются в определении класса. Следовательно, если мы хотим знать, как объявлена ​​переменная с префиксом m_ , то мы понимаем, что искать нужно в определении класса, а не внутри функции.

Обычно программисты пишут имена классов с заглавной буквы.

Правило: Пишите имена классов с заглавной буквы.

Вот ещё один пример программы с использованием класса:

Результат выполнения программы выше:

Name: John
Id: 5
Wage: $30

Name: Max
Id: 6
Wage: $32.75

В отличие от обычных функций, порядок, в котором определены методы класса, не имеет значения!

Примечание о структурах в C++

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

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

Правило: Используйте ключевое слово struct для структур, используемых только для хранения данных. Используйте ключевое слово class для объектов, объединяющих как данные, так и функции.

Заключение

Оказывается, стандартная библиотека C++ полна классов, созданных для нашего удобства. std::string, std::vector и std::array — это всё типы классов! Поэтому, когда вы создаёте объект любого из этих типов, вы создаёте объект класса. А когда вы вызываете функцию с использованием этих объектов, вы вызываете метод: