Понятие класса и объекта. Переменные-члены и функции-члены. Обращение к членам класса через объект. Указатель this. Константные функции-члены

Абстракция и декомпозиция. Основные виды декомпозиции программ.

● АБСТРАКЦИЯ - способность в выбранный момент времени игнорировать несущественные в данный момент для понимания общей картины части информации.

● ДЕКОМПОЗИЦИЯ - принцип разделения сложных систем и процессов на множество более простых отдельных отдельных частей, согласованно взаимодействующих друг с другом.

Функциональная декомпозиция

Простейшим способом устранения дупликации кода является метод ФУНКЦИОНАЛЬНОЙ ДЕКОМПОЗИЦИИ, предполагающий разбиение программы на более простые подпрограммы с передачей аргументов и возвращением результатов.

Дальнейшее дробление программы на самостоятельные функции следует делать по необходимости. Если в результате развития программы появятся другие фрагменты-дупликаты, следует добавлять функции и для них. Также, имеет смысл разбивать большие фрагменты на маленькие функции просто для уменьшения сложности восприятия, даже если не имеется никакой дупликации.

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

Структурно-функциональная декомпозиция

Взглянув на созданные функции можно сделать вывод, что практически всегда этот набор переменных передается единой группой. Это является явным признаком логической связанности этих данных, что следует подчеркнуть в виде СТРУКТУРЫ.

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

Введение структур подчеркивает дополнительные источники дупликации кода, которым ранее не уделялось достаточно внимания - моментам инициализации и освобождения последовательности. Т.к. структура является составным типом данных, становится очевидной необходимость в согласованном начальном состоянии переменных, а также в корректном освобождении занятых конкретным экземпляром структуры ресурсов.

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

Модульная декомпозиция

МОДУЛЬНАЯ ДЕКОМПОЗИЦИЯ стимулирует повторное использование фрагментов программ за счет разбиения их на отдельные модули-файлы. Данный вид декомпозиции можно применить совместно как с функциональной декомпозицией, так и со структурно-функциональным подходом.

Идея модульной декомпозиции состоит в разбиение программы на 3 физические части:

● заголовочный файл модуля

● файл реализации модуля

● клиентская часть, использующая модуль.

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

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

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

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

Преимущество модульного разбиения состоит в легкости повторного использования разработанного модуля в другой программе. В случае такой необходимости другой клиентский код может включить заголовочный файл модуля при помощи директивы #include и просто добавить файлы модуля в разрабатываемый проект без копирования. Ниже в виде стрелок представлены зависимости включения между файлами программ. Овалом выделена граница модуля. Файл реализации заполнен другим цветом, поскольку должен логически являться ”черным ящиком” для всех клиентских модулей, при этом интерфейс модуля определяется в открытом заголовочном файле::

Понятие класса и объекта. Переменные-члены и функции-члены. Обращение к членам класса через объект. Указатель this. Константные функции-члены - student2.ru

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

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

Объектная декомпозиция

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

Функции, определенные внутри структуры, называют ФУНКЦИЯМИ-ЧЛЕНАМИ, или МЕТОДАМИ. В свою очередь, переменные, определенные внутри структуры, называются ПЕРЕМЕННЫМИ-ЧЛЕНАМИ, или ПОЛЯМИ. Поскольку после помещения функций внутрь структуры появляется четко выраженная логическая связь между данными и кодом их обработки, названия следует упростить, убрав из них фрагменты, представляющие собой имя структуры.

Файл реализации видоизменяется следующим образом - перед именами функций ставится имя структуры и оператор разрешения области видимости.

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

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

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

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

Т.е., функция-член на уровне реализации является обычной функцией, содержит имя родительской структуры как часть названия, а также неявно получает адрес объекта, на котором вызывается.

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

Понятие класса и объекта. Переменные-члены и функции-члены. Обращение к членам класса через объект. Указатель this. Константные функции-члены.

Классы в С++ - это абстракция описывающая методы, свойства, ещё не существующих объектов. Объекты - конкретное представление абстракции, имеющее свои свойства и методы. Созданные объекты на основе одного класса называются экземплярами этого класса. Эти объекты могут иметь различное поведение, свойства, но все равно будут являться объектами одного класса.

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

class X  
{ int i;  
int i; // Ошибка – повторное объявление
};  
int X::k; // Ошибка – попытка объявить член класса вне объявления класса
class Y  
{ int f();  
int f(); // Ошибка – повторное объявление функции
int f(int x); // Ошибок нет
};  
class Z  
{ int f();  
int f; // Ошибка – есть функция с таким же именем
};  

Член класса не может иметь инициализатора. Член класса не может быть объявлен со спецификациями класса памяти auto, extern и register. Инициализация объектов класса осуществляется с помощью конструкторов. Объект класса не может содержать объект того же класса, но может содержать указатель или ссылку на объект того же класса.

Для доступа к членам класса (после объявления некоторой переменной этого класса или указателя на объект данного класса) используется следующий синтаксис:


<переменная> . <имя члена класса>
<указатель> -> <имя члена класса>

Функция, объявленная в классе без спецификатора friend, называется функцией-членом класса. Описание функции-члена класса относиться к области действия класса. Это означает, что функция-член класса может непосредственно использовать имена членов своего класса.

В нестатической функции-члене класса ключевое слово this обозначает указатель на объект, для которого вызвана данная функция, т.е. внутри функции-члена класса член того же класса с именем х можно обозначать как x, и как this -> x. Указатель на объект, для которого вызвана функция, является неявным параметром этой функции.

class X { private: int n; public:  
void f(int n) { this -> n = n; } }; // Члену класса n присваивается значение параметра n

Указатель this в функции-члене класса Х имеет тип X * const. Однако, это не обычная переменная, невозможно получить её адрес или присвоить ей что-нибудь. В константной функции-члене класса Х this имеет тип const X * const для предотвращения модификации самого объекта.

В большинстве случаев использование this является неявным. В частности, каждое обращение к нестатическому члену класса неявно использует this для доступа к члену соответствующего объекта.

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

class X { ... public: X& f(); }; X& X::f() { ... return *this; }

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

class X { private: int n; public: int f() const; }; int X::f() const  
{ return n++; } // Ошибка – попытка изменить значение члена класса в константной функции

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

Наши рекомендации