Скачиваний:
154
Добавлен:
08.07.2017
Размер:
4 Мб
Скачать
☆

Спецификаторы: private, protected, public.

Доступ к членам: первоначально считается все поля private, методы public. Если некоторые поля нужно наследовать делаем их protected. Остальные отступления д.б. обоснованы.

Особенности использования private и protected:

●Явный запрет выполнения соответствующих операций. Можно запретить: конструкторы, деструктор, операции преобразования типа.

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

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

class B

{

public:

virtual void f();

};

class D : public B

{

private: void f();

};

void g()

{

D d;

B *pb = &d; D *pd = &d;

pb ­> f(); // хорошо

pd ­> f(); //будет ругаться

};

(В конспекте следом еще идет коррекция доступа, но так как явного такого вопроса здесь нет, то я его не включила)

Функции ­ члены и функции ­ друзья.

Друзья ­ функции или классы, которым разрешен доступ к закрытым членам класса. Отношение дружбы не транзитивно и не наследуется.

Совместное использование функции и операции(перегрузка):

Реализуется за счет “искажения” имен. Функции получают новые имена, включающие информацию о типах и числе параметров. Не должны отличаться только типом возвращаемого значения. (int f(int) и int f(int, int ­ разные функции))

Правила перегрузки операций:

●нельзя вводить новые знаки операций;

●нельзя менять существующие;

●нельзя изменять старшинство, ассоциативность, число параметров операций;

●нельзя перегружать операции “::”, “.” и др.

●можно менять число параметров у “()” ­ вызова функции.

Операция может рассматриваться как глобальная или как операция ­ член класса.

operator @(x) или x.operator @()

Совместное использование и область видимости:

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

{

void f(int a); //a::f(5)

}

namespace b

{

void f(int a, int b); //b::f(5,10)

}

inline void f1(int n) {f1(long(n));};

Отличия функций ­ друзей от функций ­ членов:

Некоторые функции разумно реализовывать как члены класса, а некоторые ­ как друзья

class complex {

complex operator += (complex);

friend complex operator+ (complex, complex); };

Члены класса всегда имеют дополнительный неявный операнд this, для которого не применяются преобразования типа. Для friend же все операнды равнозначны.

Значения параметров по умолчанию ​Применяется вместо совместного использования

для получения коротких форм вызова функций. Значения параметров последовательно задаются справа налево в списке. Изменить значение по умолчанию нельзя. Реал­ся эф­но за счет автомати добавления соотв­го набора совместно исп­мях inline ф­ций Имеем f( , , = 3).тогда будет inline f( , ) {f ( , , 3)}

int sum(int a, int b = 3) //b=3 ­­ параметр по умолчанию

{

return a+b;

}

int s1 = sum(5); //s1=8 int s2 = sum(5, 1); //s2=6

Неопределенное число параметров​. printf (const char* …) 1ый параметр – формал строка,

которая позволяет понять кол­во и тип параметров при вызове. Для работы с переменным числом пар­ров исп­ся набор макросов из “stdorg.h”. Внутри таких функций объекты, переданные в них не считаются объектами, работа с ними осущ­ся как с фрагментами памяти. Это позволяет обойти контроль за созданием и уничтожением объектов классов, реализованный на уровне конструкторов и деструкторов.

Функционал объекты ​Прим когда требуется нечто вроде ф­ции, но с сохраненным

внутренним состоянием. Иногда такими об­тами показывают те, у кот определен оператор

class​compare_class​{

public​ :​

bool​ ​operator()(​ int​ ​A, int​ ​B) {

return​ ​(A <​​B);

}

};

// объявление функции сортировки template​<class​ ​ComparisonFunctor>​ void​sort_ints(int​ *​​begin_items, int​ ​num_items, ComparisonFunctor c);

int​main()​ {

int​ ​items[] =​​{4​,​3​,​1​,​2​};​ compare_class functor;

sort_ints(items, sizeof​ (items)​ /​sizeof​ (​int​ ),​functor);

}

Статические члены ​– члены со спецификатором static.

Создается 1 экземпляр от члена, разделяемый всеми объектами данного класса. Это ­ отдельный объект, а не подобъект! Если сущ­т const объект класса, к которого сущ­т статич член, то он не становится автоматич константным.

Обращаться можно как через класс, так и через объект: B :: st; ab.st; pb ­> st. Сущ­т еще как до момента появления 1ый объект, так и после уничтожения последнего объекта. СЧ должны быть определены в глобальной области действия. Имеют статический класс памяти и внешний тип связывания, т.к. доступны во всех

файлах, где есть описание соответствующего класса. У статических методов нет this (нельзя использовать).

Особые методы класса

1.Конструктор по умолчанию. Х::Х() ­ создается автоматически, если в классе нет других конструкторов.

2.Конструктор копирования. Х::Х([const] X&) автоматически создается только если в классе нет конструктора копирования.

3.Констр­р преобразования типа X::X{Y}

4.Операция присваивания. X::operator = (const X&) ­ если нет const, то нельзя. Создается автоматически, если не описана в классе отдельно.

5.Деструктор

▪X b;­ конструктор по умолчанию; ▪X a(b);­ копирования;

▪X a(1);­преобр­ния типа;

▪ X a = b; ­ копирования (а еще не сущ­т);

▪ a = b; ­оператор присваивания (к уже сущ­щим объектам)

Для решения проблем с неправильным преобразованиями типов при вызове конструктора можно при объявлении к­ра исп­ть спецификатор explicit, к­рый указ­т на то, что данный конструктор должен вызываться явно

string s = 'a';

explicit string (int);

Если конструктор описан с explicit, то может использоваться только явно.

14. Иерархии классов Иерархия ­​ранжированная и упорядоченная система абстракций. 2 вида: 1)классов за

счет наследование; 2) объектов за счет агрегирования. Наследование: 1)одиночное B <|­­­ D Структура объекта D:

B

часть D

}подобъект класса В 2)множественное граф.

Проблемы: дублирование полей и методов. (Внутри DD 2 подобъекта B. ) => Вирт наследование Но пробл с дублир вызовов методов не устраняется

Виртуальное наследование позволяет организовать связь между классами­братьями

VB {virtual void f{}}

 

D1 {virtual void f{}}

D2 {virtual g() {f()}}

При вызове g() из DD в подобъекте D2 внутри g()

будет исп­ся ф­ция f() класса D1. Такие классы наз­ся подклеенными.

Др рис: везде {f()}. При вызове f для DD метод f вызовется 2 раза. Та же проблема с конструкторами. Она решается след образом: введено понятие ​полный объект​– такой, который не является подобъектом базового класса другого объекта; его класс называют конечным производным. DD dd – полный, внутри него есть подобъекты, они неполные. хотя D1 d1 – полный

Правила: подобъект вирт базового класса полного объекта при множ наследовании инициализируется особым образом: 1) своим конструктором по умолчанию и остальные не выполняются; 2) либо констр­ром конечного произв класса в списке инициализации (​при этом разрешается инициализировать не прямую базу​). Все остальные инициализации игнорируются.

Таблицы вирт функций​: 1. ​Одиночное​. Пример: class B

{

public:

int b;

virtual void f(int);

virtual void g(int){return b+5}; virtual void h(int);

};

class D : public B

{

public: int d;

void g(int){return b­2};

};

class DD : public D { public:

int dd; void h(int);

};

Если в классе сущ­т хотя бы одна вирт ф­ция, в каждый объект добавл указ на табл Вирт ф­ций и создается 1 табл вирт ф­ций, содерж данные, необх­мые для вирт вызовов.

DD* pdd=new DD; pdd­>g(2); => (*(pdd­>vptr[1]))(pdd,2)

2.​Множ наслед​. Пр: :

class B1 {public: virtual void f()}; class B2 {public: virtual void f();virtual void g()}; class D:public B1, public B2 {public: void f();};

­константа времени компиляции

При исп­нии вирт ф­ций: ­увеличивается размер объектов на размер указателей; ­для каждого класса строится в памяти таблицы Вирт ф­ций. В многофайл проектах м.б. проблема размещения таблиц в файлах, учитывая принцип раздел компиляции. Для упр­ния этим процессом в среде пр­ния обычно исп­ся след опции: 1)smart virtual tables (единая) и local (создаются копии); 2)при раздел компиляции: public(в данном файле ТВФ, доступные извне) и external (ссылки на внешние таблицы)

Динамическое определение типа объекта.

Способы:

1.​добавить в объект поле “тип”. “­”­в месте, где нужно будет опр­ть тип будет конструкция switch. при добавлении нового типа эту конструкцию надо будет переписывать, что при раздельной компиляции м.б. невозможно.

2.​механизм вирт ф­ций. class ­­ пределяем тип по адресу статического поля в объекте

B {public: static int r; virtual int *mytype();}; int* B :: mytype() {return &r;}­­ возвращает адрес r class D : public B {public: static int r; virtual int *mytype();}; int* D :: mytype() {return &r;} void f(D *pb) {if (pb­>mytype()==&D::r) {…}} // признак типа – адрес статич поля

Если в классах есть вирт ф­ции, то размер объекта не увелич, иначе увелич на размер rptr, что для мелких объектов м.б. неприемлемо.

3.​Исп технологии RTTI. typeid – возвращает ссылку на объект типа type_info и м возбуждать искл ситуацию badtypeid. Класс type_info имеет: Вирт деструктор, операцию сравнения, оп упорядочения before, преобразование в тип char* для получ текстового представления имени типа. Запрещены: конструктор копирования и оп присваивания (они приватные). Данный способ позволяет добавлять в инф­цию о типе свои данные за счет наследования от класса type_info. Указатель на объект type_info добавл в ТВФ. Этот способ удобен, когда у объектов нет общего интерфейса.

4. Применение операции динамич преобразования типа. dynamic_cast <T*>(p) или <T&>

p – полиморфный указатель или ссылка (объект р привожу к типу Т) (​т.е. у объекта на кот указ д.б. вирт функ​). Позволяет опр­ть реал тип полиморф объекта. Если преобр­ние к указ­му типу невозможно, то в случае с указателем возвр­ся 0, со ссылкой – исключения bad_cast. Данная операция позволяет реал­ть ​понижающее преобразование​типа downcast, что исп­ся при орг­ции сериализации, и ​перекрестное​crosscast – для перехода м/у альтернативными переходами

15. Шаблоны. Раздельная компиляция. Наследование шаблонов

Из ответов

Шаблоны ​семейство типов или функций имеющих единое параметризованное описание. Описание конкретного типа или ф­ции генерируются по шаблону автоматически (инстанцирование­процедура получения класса по шаблону). Результат – шаблонный класс или функция. Параметры шаблона – формальные. При инстанцировании – фактические. Виды параметров шаблона: ­тип; ­Объект (значение переменной). Такой параметр в теле шаблона считается константой. Не исп­ся в шаблонных функций. ­Шаблон Раздельная компиляция. 2 подхода:

1)описание всего шаблона в заголовочных файлах. Иначе становятся недоступны при инстанцировании тела методов.

2)Раздел компиляция шаблонов. Реализация методов в отдел файле с ключ словом export:

в .h :

template <class T> void out (const T&t);

.cpp : #include “.h”

export template <class T> void out (const T&t)

Наследование шаблонов.

1)Базовый класс – обычный template < class T> class D : public B {T b}; 2)Базовый класс – шаблон template < class T> class B {T b}

template < class T> class D : public B <T> {…};

При инстанцировании будет сгенер большое кол­во шаблонных классов 3) Базовый класс ­ шаблонный класс

template < class T> class B {T b}

template < class T1> class D : public B <int>{T1 d} class F : public D<double>{...};

Позволяет сократить кол­во автоматич сгенерир классов. 4)Базовый класс ­ параметр шаблона

template < class T, class B2>

class D : public B, public B2 {…};

Позволяет организовать наследование от произвол класса пользователя.

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

контейнеры.

 

5) Передача произвольного класса базовому

template < class C > class B{C b};

template < class T > class D : public B <D<T>> {…};

Исп­ся когда в баз классе описаны операции общие для всех контейнеров, а производным явл обобщенный контейнер. Тогда для реализ некот операций необх­м тип контейнера. Передачу типа обеспеч данный способ.

Выбор алгоритма через параметр шаблона ​Проблема – в том, что необх реал­ть алг­м, к­рый работает по­разному для разных типов данных. В кач примера рассм сортировку эл­тов вектора Способы:

1)Глобальный шаблон – функция сортировки + специализация частных случаев разными шаблонными функциями /общий подход/

2)Выделение вариантной части функции в отдельный класс /функц объект/ + специализация этого класса шаблонными классами и добавление класса наследованием + реализация глобальной функции сортировки, работающей с объектом, унаследованного класса

vector <T> <|­­­ SortTableVector<T> ­­­|> Comparator<T>

3)Добавление вариантной части в кач­ве нового пар­ра ф­ции

template <class T> sort (vector<T>&v,Comparator <T>&cmp)

4) Добавление вариантной части в кач параметра шаблона. Такие пар­ры шаблона наз­ся свойства traits, интенсивно исп в STL ­ наиболее универсальный подход. Недостаток – появл нового пар­ра шаблона, но устраняется за счет значений пар­ров по умолчанию <class T=cmp<T>>.

Вызов шаблонной ф­ции м вып­ся: f( , ). проблема опр­ния пар­ров шаблона для инстанцирования. В этой ситуации исп­ся значения по умолч и делается попытка опр­ть пар­ры шаблона по типам пар­ра ф­ции. Если нам не устраивает, м явно указать фактич пар­ры при вызове ф­ции: f<,>(,)

Параметры шаблоа по типам параметра функции template <class T> void sort(T* a); //сортировка массива а int* a = new int[10];

…

sort(a); //sort <int>(a), но в данном случае int определится автоматически

специализация шаблонов.

template < class T > class vector{…}; ­ общий случай – просто шаблон template < > class vector <void*>{…}; ­ Полная специализация //указ на void

template < class T > class vector <T*> {…}; ­ частичная специализация (будет дейст­ть для указ­лей, кроме на void)

Шаблоны как параметры шаблонов​­ если в теле шаблона класса их требуется инстанцировать с разными фактич параметров, иначе следует передавать типы или объекты

template <class T1> class B{ T1 b}; ///шаблонный класс template <class T2> class C{T2 c};

C<B <int> > obj; //шаблоны, как параметры шаблонов

Шаблоны функций – опр­т потенц­но бесконечное число совместно исп­мях шаблонных ф­ций, инстанцирование к­рых вып­ся автоматически при каждом вызове ф­ции или взятии ее адреса. При вызове ф­ции если пар­р шаблона не м.б. выведен из типа пар­ра ф­ции следует исп­ть ключ слово template : m.template get<int> ();

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

16. Обработка исключительных ситуаций

Из ответов

Механизм ОИС​обесп способ передачи упр­ния из точки, где ситуация была возбуждена, в точку, где уже было управление и выражено желание обрабатывать ситуацию данного типа. В С++ реал модель ОИС с завершением – после обработки нельзя вернуться в то место, где ситуация была возбуждена, и продолжить выполнение. ОИС ориентир на последоват вып­ние пр­мы, асинхронные – не контрол­ся.

Особенности​:

1.Возбуждение ИС реал­ся конструкцией ​throw объект​; ­создается объект с пом констр по умолч и передается в точку обработки ; throw; ­ повторное возбуждение текущей ИС

try //возникает исключение

{

int a = ­2; if(a<0)

throw a; // вызываю искление

else

throw;

}

catch(int i) // Поймать исклчение, для обработки, что бы программа не упала

{

std::cout << i;

}

catch()

{

}

class DerivedException : Exception {}

2.Для контроля ИС фрагмент пр­мы д. находиться в​try {фрагмент, где контрол ИС}список реализаций​;

3.Реакция описывается в конструкции ​catch () {операторы реакции}​.Каждая реация имеет семантику, схожую с вызовом ф­ции с одним пар­ром. catch (…)­реакция на любую ИС. Порядок срабатывания реакции в конструкции try соот­т порядку реакции в списке реакций. (если первым поставить catch(…), то след никогда не сраб).

Два описание мн­ва ИС создается сис­ма классов. Возм­ны 2 способа обработки ИС:

а)ОО­ый. В базовом классе ИС опис­ся виртуал ф­ции,в произ­х – они переопр­ся; в списке реакций – ловится указатель на базовый класс; в теле реакции – работа с объектом осущ­ся через виртуал ф­ции

б) не ОО –ловится и обраб каждая ИС по отдельности.

4. Связь с конкретным классом реализуется с помощью вложенных классов​. 5​.Спецификация ИС. осущ указанием ключ слова throw после ф­ции и перчисл типы: void f() throw(A,B); ­ f возбуждает ИС A иВ; f() throw; ­ любые ИС; f() throw();­не возб ИС

6.​Вирт ф­ция не м.б. замещена в производ классе другой с не менее огр­ной спецификацией возбуждения ИС: B<­­D; B: f(), g() throw(X,Y), h() throw(X); D: f() throw(X), g()throw(X), ​h() throw(X,Y)­​ош­не м увелич число ИС

Особые случаи при обработке исключительных ситуаций.

1.ИС, возникающие в конструкторе – вызываются деструкторы для всех полностью сконструир локальных объектов. Для самого объекта деструктор не вызывается.

2.ИС при конструировании подобъекта – не вызыв деструктор ни для объекта, ни для подобъекта.

3.Возбуждена ИС, но реакции нет. Тогда она ищется в охватывающем блоке try. Если нет вообще – возбуждается стандарт ф­ция std::terminate, к­рая по умолч вызывает стандартн ф­цию abort – аварийно завершает пр­му. В пом ф­ции set_terminate м настроить terminate на вызов опр­й ф­ции.

4.Разрушен стек – terminate+abort.

5.Деструктор, вызванный при сворачивании стека из­за ИС, сам возб. ИС

(terminate+abort)

6.Функция возбуждает неуказанную ИС. Вызывается стандарт ф­ция std::unexpected, к­рая по умолч вызывает terminat+abort. Set_unexpected настраивается на пользоват ф­ция. Для борьбы с данной ситуацией м. добавить к спецификации ИС стандартную std::bad_exception – тогда при возбуждении неуказ­й ИС будет возбуждаться bad_exception. “­”­теряется инфа о первонач ИС.

Исключительные ситуации и потребление ресурсов​.

Ресурс​­ то, что м.б. занято и после исп­ния д.б. освобождено. Пр: файл, буфер. 3 стадии использования ресурса​: Получение, Использование, Освобождение.

В случае возникновения ИС на 2м этапе ресурсы могут оказаться неосвобожденными. Для решения этой проблемы созд­ся класс, образующий ​функц замыкание ​вокруг ресурса: Получение рес­сов – с пом конструктора класса. Исп­ние реал­т методы, Деструтор – освобождает. Тогда при возб ИС на 2м этапе механизм гарантирует автоматич вызов деструктора.

Еще одна проблема ­ истощение ресурсов – хотим получить ресурс, а его нет (чаще это память)

2 подхода:

1.Завершение (termination) ­ ресурс закономерно возбуждает ИС. Вызывающий код должен быть готов к ситуации подобного типа.

2.Продолжение (recuption) ­ при истощении ресурса делается попытка обращения к вызывающему коду. Если она не проходит, то происходит вызов ИС.