programming.systems.cpp.01 (1119525), страница 2
Текст из файла (страница 2)
NS::name ...;NS::SP::var += 2;#include <iostream>using namespace std;using NS::name;20Указатель thisИногда для реализации того или иного метода возникает необходимостьиметь указатель на «свой» объект, от имени которого производится вызовданного метода.В C++ введено ключевое слово this, обозначающее «указатель на себя»,которое можно трактовать как неявный параметр любого метода класса:<имя класса> * const this;*this — сам объект.Таким образом, любой метод класса имеет на один (первый) параметрбольше, чем указано явно.This, участвующий в описании функции, перегружающей операцию, всегдауказывает на самый левый (в выражении с этой операцией) операндоперации.В реальности поле this не существует (не расходуется память), и при сборкепрограммы вместо this подставляется соответствующий адрес объекта.21Специальные методы классаКонструктор — метод класса, который• имеет имя, в точности совпадающее с именем самогокласса;• не имеет типа возвращаемого значения;• всегда вызывается при создании объекта (сразу послеотведения памяти под объект в соответствии с егоописанием).Деструктор — метод класса, который• имеет имя, совпадающее с именем класса, перед первымсимволом которого приписывается символ « ~ »;• не имеет типа возвращаемого значения и параметров;• всегда вызывается при уничтожении объекта (передосвобождением памяти, отведенной под объект).22Специальные методы классаclass A {...public:A ( );A (A & y);// конструктор умолчания// A (const A & y);// конструктор копирования (КК)[explicit] A (int x);A (int x, int y);~A ();...//////////////конструктор преобразования;explicit запрещает компиляторунеявное преобразование int в АA (int x = 0, int y = 0);заменяет 1-ый, 3-ий и 4-ыйконструкторыдеструктор////////Err!, т.к.
временный объектне может быть параметром длянеконстантной ссылки в ККО.К., если будет A (const A & y)};int main () {A a1, a2 (10), a3 = a2;A a4 = 5, a5 = A(7);A *a6 = new A (1);}23Правила автоматической генерацииспециальных методов класса• Если в классе явно не описан никакой конструктор, токонструктор умолчания генерируется автоматическис пустым телом в public области.• Если в классе явно не описан конструктор копирования, тоон всегда генерируется автоматически в public областис телом, реализующим почленное копирование значенийполей-данных параметра конструктора в значениясоответствующих полей-данных создаваемого объекта• Если в классе явно не описан деструктор, то он всегдагенерируется автоматически с пустым телом в publicобласти.24Класс Boxclass Box {int l;// length – длинаint w;// width – ширинаint h;// height – высотаpublic:int volume () const { returnl * w * h ; }Box (int a, int b, int c ) { l = a; w = b; h = c; }Box (int s) { l = w = h = s; }Box ( ) { w = h = 1; l = 2; }int get_l ( ) const { return l; }int get_w ( ) const { return w; }int get_h ( ) const { return h; }};Автоматически сгенерированные конструктор копирования и операцияприсваивания:Box (const Box & a) { l = a.l;w = a.w;h = a.h; }Box & operator = ( const Box & a){ l = a.l; w = a.w; h = a.h; return * this; }Конструктор копирование и операцию присваивания можнопереопределить.25Неплоский класс stringclass string {char * p; // здесь потребуется динамическая память,int size;public:string (const char * str);string (const string & a);~string ( ) { delete [ ] p; }string & operator= (const string & a);...};string :: string (const char * str) {p = new char [ ( size = strlen (str) ) + 1];strcpy (p, str);}string :: string (const string & a) {p = new char [ (size = a.size) + 1];strcpy (p, a.p);}26Пример использования класса stringvoid f {strings1 ("Alice");s15A lice \05strings2 = s1;s24string s3 ("Kate");...s3 = s1;K ate\0s3}{...
s1...s2 {...s3...}...s1...s2}27Переопределение операции присваиванияstring & string :: operator = (const string & a) {if(this == & a)return * this;// если a = adelete [ ] p;p = new char [ (size = a.size) + 1];strcpy (p, a.p);return * this;}При этом: s1 = s2 ~ s1.operator= (s2);28Композиция (строгая агрегация) объектовclass Point {int x;int y;public:Point ( );Point ( int, int );...};Z * z = new Z (1);delete z;class Z {Point p;int z;public:Z ( int...};с ) { z = c; };// Point (); Z(1);// ~Z();~Point();Использование списка инициализации при описании конструктора:илиZ::Z ( int c ) : p (1, 2) { z = c; }Z::Z ( int c ) : p (1, 2), z (c) { }29Cсылки 1Ссылочный тип данных задается так:<тип> &Ссылка (reference) — переменная ссылочного типа.Единственная операция над ссылками — инициализация (установление связи синициализатором) при создании, при этом ссылка обозначает (именует) тот же адрес памяти,что и ее инициализатор (L-value выражение).После описания и обязательной инициализации ссылку можно использовать точно так же, каки соответствующий ей инициализатор.Фактически ссылка является синонимом своего инициализатора.Ссылочный тип данных в С++ используется в следующих случаях:a) Описание переменных-ссылок (локальных или глобальных).Например,int i = 5;int & yeti = i;// ссылка обязательно должна быть инициализирована// yeti – синоним имени i ; &i ≡ &yeti;i = yeti + 1;yeti = i + 1;cout << i << yeti; // напечатается7 730Cсылки 2b) Передача параметров в функции по ссылке.Инициализация формального параметра ссылки происходит в момент передачи фактическогопараметра (L-value выражения), и далее все действия, выполняемые с параметром-ссылкой,выполняются с соответствующим фактическим параметром.Пример:void swap (int & x, int & y) {int t = x;x = y;y = t;}Пример обращения к функции swap:int a = 5, b = 6;swap (a, b);c) Возвращение результата работы функции в виде ссылки — для более эффективнойреализации функции - т.к.
не надо создавать временную копию возвращаемого объекта — и втом случае, когда возвращаемое значение должно быть L-value-выражением.Инициализация возвращаемой ссылки происходит при работе оператора return, операндомкоторого должно быть L-value выражение. Не следует возвращать ссылку на локальный объектфункции, который перестает существовать при выходе из функции.Пример:int & f( ) {int * p = new int(5);return *p;}Пример обращения к функции f:int & x = f();31Cсылки 3d) Использование ссылок — членов-данных класса.Инициализация поля-ссылки класса обязательно происходит через списокинициализации конструктора, вызываемого при создании объекта.Пример:class A {int x;public:int & r;A( ) : r (x) {x = 3;}A (const A &);A & operator= (const A&);...};int main () {A a;...}// !!!// !!!32Cсылки 4Константные ссылкие) Использование ссылок на константу — формальных параметров функций(для эффективности реализации в случае объектов классов).Инициализация параметра — ссылки на константу происходит во времяпередачи фактического параметра, который, в частности, может бытьвременным объектом, сформированным компилятором для фактическогопараметра-константы.Пример:struct A {int a;A ( int t = 0) { a = t; }};int f (const int & n, const A & ob)return n+ob.a;}int main () {cout << f (3, 5) << endl;...}{33Временные объектыВременные объекты создаются в рамках выражений (в частности,инициализирующих), где их можно модифицировать (применятьнеконстантные методы, менять значения членов-данных).В общем случае «живут» временные объекты до окончания вычислениясоответствующих выражений.НО! Если инициализировать ссылку на константу временным объектом (вчастности, передавать временный объект в качестве параметра дляформального параметра – ссылки на константу), время его жизнипродлевается до конца жизни соответствующей ссылочной переменной.НЕЛЬЗЯ инициализировать неконстантную ссылку временным объектом (вчастности, неконстантные ссылки – формальные параметры).Пример:struct A {A (int);A (const A &);};…const A & r = A (1);// если здесь и в КК убрать const,A a1 = A (2);// все эти конструкции будутA a2 = 3; …// ошибочнымиВажно! Компилятор ВСЕГДА сначала проверяет синтаксическую исемантическую (контекстные условия) правильность, а затемоптимизирует!!!34Порядок вызова конструкторов и деструкторовПри вызове конструктора класса выполняются:1.конструкторы базовых классов (если есть наследование),2.конструкторы умолчания всех вложенных объектов в порядке ихописания в классе,3.собственный конструктор (при его вызове все поля класса ужепроинициализированы, следовательно, их можно использовать).Деструкторы выполняются в обратном порядке:1.собственный деструктор (при этом поля класса ещё не очищены,следовательно, доступны для использования),2.автоматически вызываются деструкторы для всех вложенныхобъектов в порядке, обратном порядку их описания в классе,3.деструкторы базовых классов (если есть наследование).35Вызов конструктора копирования1.
явно,2. в случае:Box a (1, 2, 3);Box b = a; // a – параметр конструктора копирования,3. в случае:Box c = Box (3, 4, 5);// сначала создается временный объект и вызывается// обычный конструктор, а затем работает конструктор// копирования при создании объекта с; если компилятор// оптимизирующий, вызывается только обычный// конструктор с указанными параметрами;4. при передаче параметров функции по значению (присоздании локального объекта);5. при возвращении результата работы функции в видеобъекта,6.
при генерации исключения-объекта.36Вызов других конструкторов• явно,• при создании объекта (при обработке описания объекта),• при создании объекта в динамической памяти (по new), при этомсначала в «куче» отводится необходимая память, а затем работаетсоответствующий конструктор,• при композиции объектов наряду с собственным конструкторомвызывается конструктор объекта – члена класса,• при создании объекта производного класса также вызываетсяконструктор и базового класса,• при автоматическом приведении типа с помощью конструкторапреобразования.37Вызов деструктора1. явно,2.
при свертке стека - при выходе из блока описания объекта, в частностипри обработке исключений, завершении работы функции;3. при уничтожении временных объектов - сразу, как только завершаетсяконструкция, в которой они использовались;4. при выполнении операции delete для указателя на объект(инициализация указателя - с помощью операции new), при этомсначала работает деструктор, а затем освобождается память.5. при завершении работы программы при удаленииглобальных/статических объектов.Конструкторы вызываются в порядке определения объектов в блоке. Привыходе из блока для всех автоматических объектов вызываютсядеструкторы, в порядке, противоположном порядку выполненияконструкторов.38.