И.А. Волкова, А.В. Иванов, Л.Е. Карпов - Основы объектно-ориентированного программирования. Язык программирования С++ (1114893), страница 4
Текст из файла (страница 4)
Это обеспечивает логическую целостность информации.После описания класса его имя можно использовать для описанияобъектов этого типа.Доступ к информационным членам и методам объекта , описаннымв открытой секции, осуществляется через объект или ссылку на объектс помощью операции выбора члена класса «.».Если работа с объектом выполняется с помощью указателя на объект, тодоступ к соответствующим членам класса осуществляется на основе указателя на член класса «−>»:class Х{public:char c;int f() {…}};int main (){Х x1;Х & x2 = x1;Х * p = & x1;int i, j, k;x1.c = ‘*’;i = x1.f();х1.с = '+';j = x2.f();x1.c = ‘#’;k = p -> f();…}Объекты класса можно определять совместно с описанием класса:class Y {…} y1, y2;3.3.
Классы и структуры С++Синтаксис класса в С++ совпадает с синтаксисом структуры С++:struct Имя_структуры { определение_членов_структуры };Класс С++ отличается от структуры С++ только определением поумолчанию первой области доступа в их описании (а также определением поумолчанию способа наследования, см. раздел 10.3):— для структур умолчанием является открытый доступ (public)— для классов умолчанием является закрытый доступ (private).Различия в умолчаниях связаны с различиями целей создания такихконструкций. Структуры создавались для объединения и совместного использования разнородных типов данных, например записей файлов. Класспредназначен для определения полноценного типа данных.21Классы и объекты С++В C++ объекты можно создавать также на основе структури объединений (union).Структуру можно рассматривать как прообраз понятия класс.
Изначально концепция структуры (например, в Си) служила исключительнообъединению разнородных данных в единой конструкции для совместнойобработки, то есть в понятии структуры присутствовала исключительно информационная составляющая. в С++ время в структуре могут бытьи функции-члены, в том числе и специальные члены — конструкторыи деструкторы, о которых будет рассказано в следующих разделах. Структуры наравне с классами можно использовать для полноценного описаниятипов данных, включающего описания операций, применяемых к описываемому типу данных. Однако наличие информационных членов в открытойсекции нарушает один из основных принципов ООП — принцип инкапсуляции.3.4. Манипуляции с состояниемобъектаДля доступа к внутренним информационным членам объекта, созданного наоснове класса (чтение/запись), необходимо использовать специальные методы класса, называемые модификаторами (setters) и селекторами (getters).Они осуществляют подконтрольное считывание и изменение внутреннихинформационных членов.
Так, если изменяется внутреннее информационноеполе size объекта класса stack, описывающее максимальный размер стека, тонеобходимо осуществить ряд действий по согласованному изменению другихинформационных членов (выделение дополнительной памяти и т. д.):class stack{int* c1;int top, size;public:. .
.int putnewsize ( int ns ){if ( top > ns ) return 1;int* nc1 = new int[ns];}if ( top > 0 )for ( int i = 0; i < top; ++I )nc1[i] = c1[i];delete c1;c1= nc1;size = ns;return 0;};Таким образом, изменение информационных полей объекта должноосуществляться специальными методами, производящими изменение требуемого информационного поля согласованно с одновременным изменениемдругих информационных полей. Такие методы обеспечивают согласованность внутренних данных объекта.22Классы и объекты С++3.5.
Класс как область видимостиКласс является областью видимости описанных в нем членов класса. Идентификатор члена класса локален по отношению к данному классу. Классымогут быть вложенными. Одноименные идентификаторы членов класса закрывают видимость соответствующих внешних идентификаторов.Операция «::» позволяет получить доступ к одноименным объектам,внешним по отношению к текущей области видимости, в частности, к глобальным функциям и переменным, следующим образом:имя_класса :: имя_члена_классаили для имен глобальных функций и переменных::: имяПример:int ia1;void f1 ( int b1 ){ia1 = ia1 + b1;}class x{int ia1;public:x() { ia1 = 0; }void f1 ( int b1 ){::f1(b1); // вызов глобальной функции}};int main(){x a2;a2.f1(2);return 0;}3.6.
Объявление и определениеметодов класса.Спецификатор «inline»Каждый метод класса, должен быть определен в программе. Определитьметод класса можно либо непосредственно в классе (если тело метода неслишком сложно и громоздко), либо вынести определение вне класса,а в классе только объявить соответствующий метод, указав его прототип.23Классы и объекты С++При определении метода класса вне класса для указания области видимости соответствующего имени метода используется операции «::»Пример:class x{int ia1;public:x() { ia1 = 0; }int func1();};int x::func1() { … return ia1; }Это позволяет повысить наглядность текста, особенно, в случае значительного объема кода в методах. При определении метода вне классас использованием операции «::» прототипы объявления и определенияфункции должны совпадать.Метод класса и любую функцию, не связанную ни с каким классом,можно определить со спецификатором inline:inline int func1();Такие функции называются встроенными.Спецификатор inline указывает компилятору, что необходимо по возможности генерировать в точке вызова код функции, а не команды вызовафункции, находящейся в отдельном месте кода модуля.
Это позволяетуменьшить время выполнения программы за счет отсутствия команд вызовафункции и возврата из функции, которые кроме передачи управления выполняют действия соответственно по сохранению и восстановлению контекста (содержимого основных регистров процессора). При этом размермодуля оказывается увеличенным по сравнению с программой без спецификаторов inline.
Следует отметить, что спецификатор inline является рекомендацией компилятору. Данный спецификатор неприменим для функций сосложной логикой. в случае невозможности использования спецификатора дляконкретной функции компилятор выдает предупреждающее сообщениеи обрабатывает функции стандартным способом.По определению методы класса, определенные непосредственнов классе, являются inline-функциям3.7. Указатель «this»В классах С++ неявно введен специальный указатель this — указатель натекущий объект.
Каждый метод класса при обращении к нему получаетданный указатель в качестве неявного параметра. Через него методы классамогут получить доступ к другим членам класса.Указатель this можно рассматривать как локальную константу, имеющую тип X*, если X — имя описываемого класса. Нет необходимости ис-24Классы и объекты С++пользовать его явно. Он используется явно, например, в том случае, когдавыходным значением для метода является текущий объект.Данный указатель, как и другие указатели, может быть разыменован.При передаче возвращаемого значения метода класса в виде ссылки натекущий объект используется разыменованный указатель this, так как ссылка,как уже было указано, инициализируется непосредственным значением.Пример:class x{.
. .public:x& f(. . .){. . .return *this;}};3.8. Указатель на член классаКроме адресации областей памяти, содержащих информационные объекты,указатели могут содержать адреса членов класса. Технологию созданияи использования таких указателей легче описать с использованием конкретного примера, операторы которого подробно прокомментированы:class X{int i;public:Х() {i = 1;}int f1(int j){cout << "print i" << i << "\n";return j;}int f2(int j){cout << "reset i \n"; i = 1;return j;}int f3(int j){cout << "set i \n"; i = j;return j;}};typedef int (Х::* pf)(int); // см. комментарий 1)int main(){int k, sw, par;25Классы и объекты С++x b;pf ff;.
. .switch (sw){case 1: ff=&x::f1;break;case 2: ff=&x::f2;break;case 3: ff=&x::f3;};k = (b.*ff)(par);. . .return 0;// см. комментарий 2)// см. комментарий 3)// см. комментарий 4)}Комментарии:1) ключевое слово typedef вводит новое имя для типа:typedef int (Х::* pf)(int);где pf — тип указателя на метод класса X с одним входным параметром типа int и типом возвращаемого значения — int.2) pf ff; — создание объекта ff, имеющего введенный тип pf.3) ff = &Х::f1; — указателю ff присваивается адрес одного из методовкласса. Доступ к этому методу по данному указателю через какой-либо объект невозможен (оператор ff = &b.f1; — неверен). Делов том, что указатель на член класса представляется для нестатических членов не абсолютным, а относительным адресом, то естьсмещением относительно базового адреса класса (указатель на статический член класса представляет собой истинный адрес).4) k = (b.* ff)(par); — разыменование указателя на нестатический методкласса дает доступ к коду по относительному адресу, который применяется к базовому адресу конкретного объекта (в данном случае — объекта b).ПримечаниеВ случае объявления методов статическими членами (см.
раздел «Статическиечлены класса») идентификатор pf необходимо объявить обычным указателемна функцию:typedef int (* pf)(int);Разыменование объекта такого типа представляется обычным разыменованием указателя на функцию:k = (*ff)(par);Применение техники разыменования указателя на метод класса является проявлением динамического полиморфизма, когда исполняемый коддля одного и того же оператора (k = (b.*ff)(par)) определяется на этапе исполнения, а не компиляции.
в большей мере динамический полиморфизмреализуется виртуальными функциями, описываемыми в следующих разделах.26Конструкторы и деструкторыГлава 4.Конструкторыи деструкторыКонструкторы и деструкторы являются специальными методами класса.Конструкторы вызываются при создании объектов класса и отведении памяти под них. Деструкторы вызываются при уничтожении объектови освобождении отведенной для них памяти.В большинстве случаев конструкторы и деструкторы вызываются автоматически (неявно) соответственно при описании объекта (в момент отведения памяти под него) и при уничтожении объекта. Конструктор (каки деструктор) может вызываться и явно, например, при создании объектав динамической области памяти с помощью операции new.Так как конструкторы и деструкторы неявно входят в интерфейс объекта, их следует располагать в открытой области класса.ПримечаниеКонструкторы и деструкторы могут располагаться и в закрытой области дляблокирования возможности неявного создания объекта.
Но в этом случае явное создание объекта возможно только при использовании статических методов, являющихся частью класса, а не конкретного объекта. Статическиеметоды описываются далее.Отличия и особенности описания конструктора от обычной функции:1) имя конструктора совпадает с именем класса;2) при описании конструктора не указывается тип возвращаемогозначения.Следует отметить, что и обычная процедура может не возвращать значения, а только перерабатывать имеющиеся данные.