Скачиваний:
152
Добавлен:
08.07.2017
Размер:
4.08 Mб
Скачать

Спецификаторы: 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”. Внутри таких функций объекты, переданные в них не считаются объектами, работа с ними осущ­ся как с фрагментами памяти. Это позволяет обойти контроль за созданием и уничтожением объектов классов, реализованный на уровне конструкторов и деструкторов.

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

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

classcompare_class{

public:

bool​ ​operator()(intA, intB) {

return(A <B);

}

// объявление функции сортировки template<classComparisonFunctor>voidsort_ints(int*begin_items, intnum_items, ComparisonFunctor c);

intmain(){

intitems[] ={4,3,1,2compare_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) ­ при истощении ресурса делается попытка обращения к вызывающему коду. Если она не проходит, то происходит вызов ИС.