240 likes | 521 Views
Лекция 10. Объекты. ООП. Инкапсуляция Возможность совместного хранения данных и кода для их обработки Наследование Возможность расширять существующие объекты новыми данными и/или методами Полиморфизм Возможность использовать дочерние объекты там, где требуются родительские. Инкапсуляция.
E N D
Лекция 10 Объекты
ООП • Инкапсуляция Возможность совместного хранения данных и кода для их обработки • Наследование Возможность расширять существующие объекты новыми данными и/или методами • Полиморфизм Возможность использовать дочерние объекты там, где требуются родительские
Инкапсуляция • Набор данных и функций для их обработки описывается классом • Класс является пользовательским типом данных. Объекты такого типа называются экземплярами класса • Функции-члены класса называются его методами • Данные класса называются его полями
Объявление и определение классов • Объявление Как и любое объявление, может встречаться сколько угодно раз в единице трансляции • Определение Может повторяться в разных единицах трансляции struct A ; class B ; struct A { int data ; } a ; class B { intfoo ( int n ) { return n + a.data ; } A a ; };
Управление доступом • public: открытый доступ К членам класса (данным и методам) возможен доступ из любой точки программы • protected: защищенный доступ Доступ к членам класса возможен только из методов класса, а также из методов его потомков • private: закрытый доступ Доступ к членам класса возможен только из его собственных методов class B { public: B( int n ) { n_ = n ; } intFoo ( int a ) { return n_ + a ; } protected: void set ( int k ) { n_ = k ; } private: intn_ ; intm_n ; };
Различие classи struct • class По умолчанию все члены данных имеютдоступ private. • struct По умолчанию все члены данных имеют доступ public. struct A { int data ; float data2 ; }; class A { public : int data ; float data2 ; };
Ключевое слово friend • Открывает доступ «для избранных» Ключевое слово friendпозволяет указать «дружественную» функцию или класс, которые будут иметь доступ ко всем членам данного класса вне зависимости от их спецификаторов доступа. struct A { friend structB ; friend void foo ( A &, int ); private : int data ; float data2 ; }; void foo ( A & a, int b ) { a.data = b ; } struct B { A a ; void some () { a.data2 = 3.7f ; } };
Статические поля и методы • Статические члены класса Переменные и функции, которые входят в состав класса, но не являются частью экземпляра этого класса, называются статическими. • Определение Статические поля требуют обязательного определения вне класса. такое определение может быть снабжено инициализатором struct Complex { Complex () { re = def ; im = def ; } float re, im ; static float def ; staticvoidset_def ( float d ) { def = d ; } }; // Где-то внутри .cpp float Complex::def = 0.0f ;
Статические константы • Инициализация вне конструктора Статическое константное поле интегрального типа может быть инициализировано константным выражением при объявлении. Если требуется иметь такое поле в памяти, его требуется обязательно определить вне определения класса. class A { static const intc1 =2 ; //ок! static intc2 = 2 ; // не константное поле const int c3 = 2 ; // не статическое поле static const intc4 = f ( 7 ); // инициализатор не константа static const float f = 0.7 ; // Не интегральный тип };
Паттерн «Singleton» • Паттерн «Singleton» Используется когда необходимо гарантированно иметь не более одного экземпляра некоторого класса. struct Singleton { static Singleton & get() { static Singleton s ; return s ; } int data ; private : Singleton (){} }; Singleton::get().data = 4 ;
Ключевое слово this • Действительно только в пределах нестатических методов класса • Действительно только для сконструированных объектов • Является указателем на текущий экземпляр класса struct A { void f ( int b ) { a = b ; this->b = b ; } int a, b ; };
Методы • Метод Функция, определенная внутри класса. Имеет доступ ко всем членам класса, без указания каких-либо спецификаторов принадлежности. • Объявление Объявление метода класса всегда внутреннее. Невозможно объявить метод класса вне его определения. • Внутреннее определение Функция, определенная внутри определения класса, является встраиваемой (inline) и подчиняется всем правилам встраиваемых функций (в том числе правил множественного определения) • Внешнее определение Внешнее определение метода подчиняется всем правилам обычных функций, в том числе правилу одного определения. Для внешнего определения функции требуется указать имя соответствующего класса
Внешнее и внутреннее определение File.h struct File { File ( const char * fn ) { f_ = fopen ( fn, “rt” ); } void Read (void *, int); private : FILE * f_ ; }; File.cpp #include “File.h” void File::Read (void * data, int size ) { fread ( data, size, 1, f_ ); }
Константные методы • Константные методы Методы, не изменяющие данные класса struct Date { int day () const { return d ; } int month () const ; int reset () { /*...*/} private: int d, m, y ; }; int Date::month () const { return m++ ; // ошибка! } Date d ; std::cout << d.day(); Date constcd ; std::cout << cd.day (); d.reset (); cd.reset(); // Ошибка!
Ключевое слово mutable • Применяется только к данным классов • Указывает, что это поле может изменяться, даже если объект константный (или из константной функции) • Чаще всего используется для кеширования вспомогательных данных
Конструкторы • Конструктор Метод для инициализации данных класса. Имя конструктора всегда совпадает с именем класса. Вызывается непосредственно после того, как сконструированы все базовые классы, но еще не инициализированы данные текущего класса • Всегда существует Если для класса не указан конструктор, создается конструктор по умолчанию. Такой конструктор автоматически инициализирует данные класса там, где это возможно. • Не единственный В классе может быть более одного конструктора, в этом случае они подчиняются правилам перегрузки. Нельзя вызвать один конструктор из другого. • Не возвращает значений
Пример struct Date { Date () {} Date ( const char * ) {} Date ( int d, int m, int y ) {} Date ( long timestamp ) {} private: int day ; intmon ; int year ; }; struct Undead { const int & c ; }; Undead zombie ; // Ошибка
Конструктор копирования • Является конструктором Имя конструктора копирования совпадает с именем класса. Он имеет единственный аргумент – константную ссылку на экземпляр того же класса. • Всегда существует Если конструктор копирования не объявлен, он создается автоматически. В этом случае осуществляется побитовое копирование данных исходного объекта в конструируемый struct A { int data ; }; A a ; A b ( a ); struct A { A ( A const & a ); }; A a ; A b ( a ); // Ошибка
Инициализация данных • Данные инициализируются в конструкторе В определении конструктора можно указать список инициализации – список начальных значений членов класса. • Порядок инициализации Данные инициализируются в том порядке, в котором они объявлены внутри класса. Гарантируется, что в том же порядке данные будут расположены в памяти struct A { A () : a ( 1 ), c ( 12 ), b ( 32 ), e ( d ), d ( 10 ) , date ( 2009, 12, 01 ) {} int a, b, c, d, e; Date date ; };
Деструкторы • Деструктор Метод для деинициализации данных класса. Вызывается непосредственно перед удалением памяти, выделенной под объект. Имя деструктора совпадает с именем класса, с добавлением префикса ~. Обычно служит для удаления дополнительной памяти и освобождения ресурсов. • Всегда один У класса всегда существует деструктор. Если таковой не указан, создается автоматически. • Независим Деструктор не принимает параметров и не возвращает значений
Конструирование и уничтожение • Именованный автоматический объект Создается: каждый раз, когда встречается его объявление Удаляется: при выходе из соответствующего блока • Объект в свободной памяти Создается: с помощью оператора new Удаляется: c помощью оператора delete • Нестатический объект в составе другого Создается: при конструировании родительского объекта Удаляется: при уничтожении родительского объекта • Элемент массива Создается: при создании содержащего его массива Удаляется: при удалении содержащего его массива
Конструирование и уничтожение • Временный объект Создается: при вычислении значения выражения Удаляется : по окончании вычисления выражения • Локальный статический объект Создается: при первом появлении его определения Удаляется: при завершении программы • Глобальный объект Создается: при старте программы Удаляется: при завершении программы • Объект, созданный путем размещения Создается: в момент размещения в памяти. Удаляется: вручную (явным вызовом деструктора) • Объект в составе объединения Не может иметь конструктора и деструктора
RAII • RAII (Resource Acquisition Is Initialization) Паттерн проектирования, при котором получение некоторого ресурса осуществляется в конструкторе, а освобождение – в деструкторе. struct File { File ( const char * fn ) { f_ = fopen ( fn, “rt” ); } ~File () { fclose ( f_ ); } void Read ( ... ) {} private : FILE * f_ ; }; voidfoo () { // ... File f ( “in.txt” ); f.Read ( ... ); f.Read ( ... ); // ... }
Ключевое слово explicit • Запрет неявного вызова конструктора Если в некотором выражении в качестве lvalueвыступает объект, у которого объявлен конструктор от одного аргумента, а rvalue – значение того же типа, что и аргумент, осуществляется неявное конструирование объекта. Ключевое слово explicitзапрещает подобного рода действия. structA { A ( int c ) : n_ ( c ) {} private : int n_ ; }; structB { explicit B ( int c ) : n_ ( c ) {} private : int n_ ; }; A foo () { A a1 ( 7 ); B b1 ( 9 ); B b2 = 3 ; return 7 ; } B bar () { return 42 ; }