рефераты конспекты курсовые дипломные лекции шпоры

Реферат Курсовая Конспект

Шаблони

Шаблони - раздел Программирование, Процедурно-орієнтоване (структурне) програмування Шаблони Розширюють Поняття Функції Й Класу, Надаючи Можливості Їхньої Парамет...

Шаблони розширюють поняття функції й класу, надаючи можливості їхньої параметризації, тобто оголошення функцій і класів у термінах «будь-якого типу».

2. Шаблони функцій

Шаблон функції – це оголошення функції, що випереджається специфікацією шаблона. Специфікація шаблона складається із ключового слова template, за яким має бути список параметрів, обмежений кутовими дужками <>.

Шаблони функцій мають параметри типу, які позначаються ключовим словом class, за котрим іде ідентифікатор. Ідентифікатор служить для заміщення імені типу. Може бути більше одного параметра типу.

Шаблони функцій автоматично розширюються транслятором до повного опису функції так, як це необхідно.

 

Приклад:

 

#include <iostream>

 

using namespace std;

 

// оголошення: максимум із двох значень типу Т

template <class T>

const T& Max (const T&, const T&);

 

void main()

{

int i=5, j=10;

float a=1.5, b=1.7;

int k = Max(i, j); // виклик Max(int, int)

float c = Max (a, b); // виклик Max(float, float)

cout<<k<<'t'<<c<<endl;

}

 

// визначення

template <class T>

const T& Max (const T& a, const T& b)

{

return a>b?a:b;

}

 

Шаблони функцій можуть бути перевантажені іншими функціями-шаблонами або звичайними функціями.

 

template <class T> const T& Max (const T&, const T&);

template <class T> const T& Max(const T*, int);

 

Для певних типів шаблони функцій можуть бути перекриті для того, щоб виконувати (або не виконувати) які-небудь дії, які функції-шаблони не виконують (чи виконують).

 

const char* Max (const char* c, const char* d)

{

// виконати що-небудь, специфічне для char*

}

3. Шаблони класів

Шаблони класів – це оголошення класів, що випереджаються специфікацією template. Автоматично розширюються компілятором до повних визначень класів так, як це необхідно. Шаблони класів не можуть бути вкладені в інші класи (на відміну від інших класів).

 

// оголосити клас Stack, що представляє

// собою стек для будь-яких типів

template <class T>

class Stack

{

T* v; // покажчик на деякий тип Т

int size, top;

public:

Stack(int ezis);

~Stack();

void Push(const T&); // помістити Т у стек

T& Pop(); // витягти Т зі стека

T& Top()const;

};

 

// ...

Stack <int> i; // стек для int

Stack <char*> cp; // стек для char*

 

Шаблони класів можуть мати нетипізовані (або тільки нетипізовані) параметри. Значення, зазначені для цих параметрів, повинні бути константними виразами.

 

// передати розмір як параметр шаблона

template <class T, int size>

class Stack

{

T v[size]; // масив елементів типу Т

int top;

public:

Stack():top(-1){}

// ...

};

// ...

 

Stack <int, 20> tiny;

Stack <int, 500> huge;

 

Хоча стеки tiny і huge зберігають тип int, це різні типи, оскільки вони мають різний розмір стека. Це можна проілюструвати тим, що покажчик Stack<int, 20> – це не те ж саме, що покажчик на Stack<int, 500>:

 

Stack<int, 20>* is20p = &tiny; // правильно

Stack<int, 500>* is500p = &tiny; // помилка

 

Шаблонові класи можуть бути породжені як від нешаблонних класів, так і від класів- шаблонів. А також можуть породжувати як нешаблонні класи, так і класи-шаблони.

 

class A {/* … */};

template <class T> class B: public A{/* … */};

template <class T> class C: public B{/* … */};

class D: public C<int> {/* … */};

Для певних типів шаблони класів можуть бути перекриті для того, щоб виконувати (або не виконувати) які-небудь дії, які шаблони класів не виконують (чи виконують).

 

// оголосити свій власний стек для char*

class Stack<char*>

{

char** v; // покажчик на char*

int size, top;

public:

Stack (int ezis);

~Stack();

void Push(const char*);

char* Pop();

char* Top() const;

};

Шаблонові класи можуть також бути класами-структурами або класами-об’єднаннями.

4. Статичні дані-члени

Статичні дані-члени класу розділяються всіма об’єктами класу для кожного конкретного екземпляра класу-шаблона. Статичні дані-члени класу визначаються в області видимості файлу (як і всі статичні поля), коли визначення випереджається специфікацією template.

 

template <class T>

class C

{

static int i; // звичайне статичне поле

static T t; // параметризоване

// ...

};

template <class T> int C<T>::i; // визначити в області

template <class T> T C<T>::t; // видимості файлу

// ...

C<char> c; // має int C::i і char C::t

C<float> f; // має int C::i і float C::t

5. Шаблони функцій-членів

Шаблони функцій-членів визначаються поза оголошеннями класів, до яких вони належать, за допомогою специфікації template.

 

template <class T>

void Stack<T>::Push(const T& element)

{

if(top == size - 1)

error("Stack overflow");

else

v[++top] = element;

}

 

Для певних типів шаблони функцій-членів можуть бути перекриті для того, щоб виконувати (або не виконувати) які-небудь дії, які шаблони функцій-членів не виконують (чи виконують).

 

void Stack<char*>::Push(const char* cepr)

{

// виконати щось особливе з char*

}

6. Дружні функції

Дружні функції для кожного типу Т можуть бути друзями всіх класів типу Т. Це звичайні дружні функції.

Дружні функції можуть випереджатися специфікацією template. Для типів Т і U функції-шаблони типу U є дружніми функціями кожному класу типу Т.

 

template <class T>

class Person

{

friend void Pet();

template <class T> friend void Spouse(Person&);

template <class U> friend void Coworker(U&);

};

// ...

void Pet() // звичайна функція

{

// ...

}

 

template <class T>

void Spouse(Person& p)

{

// ...

}

 

template <class U>

void Coworker(U& u)

{

// ...

}

 

Тут Pet() – функція, дружня Person <T> для кожного типу Т.

 

 
 


Pet()

Person<int>
Person<char>
Person<float>

 

Для будь-якого типу Т, скажімо, int, Spouse(Person<int>&) – функція, дружня Preson<int>, але не Person<char> або будь-якому іншому типу.

 

Spouse(Person<int>&) Person<int>
Spouse(Person<char>&) Person<char>
Spouse(Person<float>&) Person<float>

 

Coworker(U&) – функція, дружня Person<T>, для будь-якого типу Т і будь-якого типу U.

 

Coworker(int&) Person<int>
Coworker(char&) Person<char>
Coworker(float&) Person<float>

 

 

Дружні функції можуть бути функціями-членами іншого класу.

 

template <class T>

class Person

{

friend void Family::Sibling();

friend void Acquaintance::Casual(Person&);

template <class U> friend void Neighbor<U>::NextDoor(U&);

};

 

Тут Family::Sibling() – функція, дружня Person<T>, для кожного типу Т. Для будь-якого типу Т, скажімо, для int, Acquaintance::Casual(Person<int>&) – функція, дружня Person<int>, але не Person<char> або будь-якому іншому типу.

Neighbor<U>::NextDoor(U&) – функція, дружня Person<T>, для будь-якого типу U.

Дружні функції можуть бути оголошені для всього класу.

 

template <class T>

class Person

{

friend class Family;

friend class Acquaintance;

template <class U> friend class Neighbor;

};

 

Тут для кожного типу Т усі функції-члени класу Family – це функції, дружні Person<T>. Для будь-якого типу Т, скажімо, для int, усі функції класу Acquaintance<int> є друзями Person<int>, але не Person<char> або будь-якого іншого типу.

Для кожного типу Т і кожного типу U всі функції-члени Neighbor<U> є друзями Person<T>.

Дружні функції можуть також бути друзями нешаблонних класів.

 

Приклад:

 

// TDatabase.h

 

#ifndef __TDATABASE_H

#define __TDATABASE_H 1 // запобігання декільком #include

 

template <class T>

class TDatabase

{

T* rp; // покажчик на записи

int num; // кількість записів

public:

TDatabase(int n)

{

rp = new T[num = n];

}

~TDatabase(void)

{

delete[] rp;

}

 

T& GetRecord(int recnum);

};

 

template <class T>

T& TDatabase<T>::GetRecord(int recnum)

{

T* crp = rp; // покажчик на поточний запис = покажчик на записи

if(0 <= recnum && recnum < num)

while(recnum-- > 0)

crp++;

return *crp;

}

 

 

#endif // __TDATABASE_H

 

// CTemplat.cpp

#include <iostream>

#include <cstring>

#include "TDatabase.h"

 

using namespace std;

 

class TRecord

{

private:

char name[41];

public:

TRecord()

{

name[0] = 0;

}

TRecord(const char* s)

{

Assign(s);

}

char* GetName(void)

{

return name;

}

void Assign(const char* s)

{

strncpy(name, s, 40);

}

};

 

void main()

{

int rn; // індекс кількості записів

TDatabase<TRecord> db(3); // база даних із трьох TRecord

TDatabase<TRecord*> dbp(3); // із трьох покажчиків

TDatabase<TRecord> *pdb; // покажчик на базу даних

TDatabase<TRecord*> *ppdb; // покажчик на базу даних покажчиків на

//TRecord

 

cout<<"nnDatabase of 3 TRecordsn";

db.GetRecord(0).Assign("George Washington");

db.GetRecord(1).Assign("John Adams");

db.GetRecord(2).Assign("Thomas Jefferson");

for(rn=0; rn<=2; rn++)

cout<<db.GetRecord(rn).GetName()<<'n';

 

cout<<"nnDatabase of 3 TRecord pointersn";

dbp.GetRecord(0) = new TRecord("George Bush");

dbp.GetRecord(1) = new TRecord("Ronald Reagan");

dbp.GetRecord(2) = new TRecord("Jimmy Carter");

for(rn=0; rn<=2; rn++)

cout<<dbp.GetRecord(rn)->GetName()<<'n';

 

cout<<"nnPointer to Database of 3 TRecordsn";

pdb = new TDatabase<TRecord>(3);

pdb->GetRecord(0).Assign("John Adams");

pdb->GetRecord(1).Assign("Thomas Jefferson");

pdb->GetRecord(2).Assign("Aaron Burr");

for(rn=0; rn<=2; rn++)

cout<<pdb->GetRecord(rn).GetName()<<'n';

 

cout<<"nnpointer to Database of 3 TRecord pointersn";

ppdb = new TDatabase<TRecord*>(3);

ppdb->GetRecord(0) = new TRecord("Dan Quayle");

ppdb->GetRecord(1) = new TRecord("George Bush");

ppdb->GetRecord(2) = new TRecord("Walter Mondale");

for(rn=0; rn<=2; rn++)

cout<<ppdb->GetRecord(rn)->GetName()<<'n';

 

}

 

 


Лекція 17. Виняткові ситуації

1. Виняткові ситуації

Виняткова ситуація – це ні що інше, як умова виняткової ситуації, що вимагає спеціальної обробки.

Для збудження виняткової ситуації оператор посилає (throw) об’єкт, що описує суть виняткової ситуації. Об’єкт може бути літеральним значенням, рядком, об’єктом класу або будь-яким іншим об’єктом.

Для обробки виняткової ситуації деякий оператор перехоплює (catch) умову, надіслану деяким процесом. Оператори, що перехоплюють виняткові ситуації, називаються оброблювачами виняткових ситуацій.

Програми підготовлюються до перехоплення виняткових ситуацій, випробовуючи (try) один або кілька процесів, що збуджують виняткові ситуації. Загалом для використання виняткових ситуацій ви випробовуєте один чи декілька операторів і перехоплюєте будь-яку виняткову ситуацію, що збуджена цими операторами.

2. Використання виняткових ситуацій

Звичайно в класі виняткової ситуації реалізуються функції-члени, які можна викликати у виразах усередині catch.

 

class Overflow

{

public:

void Report()

{

cout<<"Error: overflow"<<endl;

}

};

 

Ви можете послати екземпляр цього класу для збудження виняткової ситуації (припустимо, всередині функції)

 

throw Overflow();

 

В операторі catch можна викликати Report() об’єкта виняткової ситуації для відображення повідомлення про помилку:

 

catch(Overflow overObject)

{

overObject.Report();

}

3. Збудження декількох виняткових ситуацій

У функціях можна збуджувати об’єкти виняткових ситуацій різних типів для підтримки різних умов виняткових ситуацій.

 

int AnyFunction()

{

if(condition1)

throw "Big trouble!n"; // послати рядковий об'єкт

if(condition2)

throw Overflow(); // послати об'єкт класу

return 123; // якщо немає проблем, повернути значення

}

 

Функції можуть збуджувати одну або кілька виняткових ситуацій різних типів, що представляють різні умови виняткових ситуацій.

Збудження виняткової ситуації негайно завершує виконання функції, у якій виконується оператор throw.

Виняткові ситуації забезпечують альтернативний механізм повернення для функцій. Можна підтримувати кілька типів об’єктів виняткових ситуацій за допомогою серії операторів catch.

 

catch(Error e)

{

// обробка виняткової ситуації для класу Error

}

catch(const char* message)

{

// обробка виняткової ситуації для рядків

}

4. Використання блоків try

try

{

cout<<"Here we go!"<<endl;

int x = AnyFunction();

cout<<"x == "<<x<<endl;

}

catch(const char* message)

{

cout<<"Error! "<<message<<endl;

exit(-1); // необов'язково

}

catch(Overflow)

{

cout<<"Overflow!"<<endl;

exit(-2); // необов'язково

}

 

Якщо у функції AnyFunction() виникла виняткова ситуація, блок try негайно завершується, тобто будь-яка умова виняткової ситуації приводить до пропуску присвоювання х і завершального оператора виведення. У цьому прикладі два оператори catch обробляють виняткові ситуації для рядків і класу Overflow. Будь-які інші типи виняткових ситуацій, не оброблювані операторами catch, передаються нагору по ланцюжку викликів. Якщо жодний оператор catch відповідного типу не був знайдений, виконання програми переривається викликом спеціального оброблювача виконуючої системи.

5. Оголошення виняткових ситуацій

 

void AnyFunction()throw(Error);

 

Наступний за ім’ям функції й списком параметрів (порожнім у цьому випадку) вираз throw() указує, що функція AnyFunction() може збуджувати виняткові ситуації типу Error. Подібне оголошення вказує компіляторові, що функції AnyFunction() не дозволяється збуджувати виняткові ситуації інших типів.

Для визначення функції, що збуджує виняткові ситуації декількох типів, варто перелічити типи даних об’єктів виняткових ситуацій, відділені одне від одного комами в круглих дужках:

void AnyFunction()throw(Overflow, const char*);

 

6. Написання оброблювачів виняткових ситуацій

Приклад:

 

#include <iostream>

#include <cmath>

 

using namespace std;

 

class Error;

 

void Run();

double Pow(double b, double e);

double Power(double b, double e)throw(Error);

 

class Error

{

double b;

double e;

public:

Error()

{

cout<<"Error in source code!"<<endl;

}

Error(double bb, double ee):b(bb),e(ee){}

void Report();

};

 

int main()

{

for(;;)

{

try

{

Run();

cout<<"Program is ending normally"<<endl;

return 0;

}

catch(...)

{

cout<<"Error detected: try again!"<<endl;

}

}

}

 

void Run()

{

try

{

double base, exponent, result;

cout<<"Base?";

cin>>base;

cout<<"Exponent?";

cin>>exponent;

result = Power(base, exponent);

cout<<"Result == "<<result<<endl;

}

catch(Error e)

{

e.Report();

throw e;

}

}

 

double Pow(double b, double e)

{

return exp(e * log(b));

}

 

double Power(double b, double e)throw(Error)

{

if(b>0.0)

return Pow(b, e);

if(b<0.0)

{

double ipart;

double fpart = modf(e, &ipart);

if(fpart == 0)

{

if(fmod(ipart, 2) != 0)

return -Pow(-b, e);

else

return Pow(-b, e);

}

else

throw Error(b, e);

}

else

{

if(e == 0.0)

return 1.0;

if(e < 1.0)

throw Error(b, e);

return 0.0;

}

}

 

void Error::Report()

{

cout<<"Domain error:"

<<" base: "<<b

<<" exponent: "<<e

<<endl;

}

7. Неопрацьовані виняткові ситуації

Якщо в програмі виникли неопрацьовані виняткові ситуації, то за замовчуванням викликається функція unexpected(). Звичайно функція unexpected() викликає функцію terminate(), що, у свою чергу, викликає функцію abort() для аварійного завершення програми. Ви можете замінити функції unexpected() і terminate() своїми функціями-оброблювачами виняткових ситуацій. Замінити функцію abort() не можна.

8. Виняткові ситуації й локальні об’єкти

Покажчики на об’єкти не видаляються автоматично. Якщо ви створюєте динамічний об’єкт, ви самі відповідальні за його видалення перед збудженням виняткової ситуації.

 

int AnyFunction()

{

AnyClass* p = new AnyClass(123);

// . . .

if(condition)

{

delete p;

throw Error();

}

delete p;

return 123;

}

9. Виняткові ситуації й конструктори

class AnyClass

{

OtherClass x;

public:

AnyClass():x(123)

{

if(condition)

throw Error();

}

~AnyClass(){}

};

 

Об’єкт х типу OtherClass створюється конструктором AnyClass до того, як будуть виконуватися оператори в тілі конструктора. Якщо конструктор OtherClass збуджує виняткову ситуацію, інші оператори конструктора не виконуються. Оскільки код конструктора не виконався, об’єкт класу AnyClass не створюється, і, отже, деструктор AnyClass не викликається.

 

 


 

Список рекомендованої літератури

 

1. Харви Дейтел. Как программировать на С++ / Х. Дейтел, П. Дейтел; 3-е изд-е, пер. с англ. – М. : ЗАО «Изд-во БИНОМ», 2001. – 1152 с.

2. Глушаков С.В. Язык программирования С++ / С.В. Глушаков, А.В. Коваль,
С.В. Смирнов – Х.: Фолио, 2002. – 500 с.

3. Щедріна О.І. Алгоритмізація та програмування процедур обробки інформації: навч. посібник / О.І. Щедріна. – К.: КНЕУ, 2001. – 240 с.

4. Фаулер М. UML. Основы / М. Фаулер, К. Скотт; – пер. с англ. – СПб: Символ – Плюс, 2002. – 192 с., ил.

5. Леоненков А.В. Самоучитель по UML. [Электронный ресурс]. – Режим доступа: http://khpi-iip.mipk.kharkiv.edu/library/case/index.html.

 

 


 

НАВЧАЛЬНЕ ВИДАННЯ

 

– Конец работы –

Эта тема принадлежит разделу:

Процедурно-орієнтоване (структурне) програмування

На сайте allrefs.net читайте: "Процедурно-орієнтоване (структурне) програмування"

Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: Шаблони

Что будем делать с полученным материалом:

Если этот материал оказался полезным ля Вас, Вы можете сохранить его на свою страничку в социальных сетях:

Все темы данного раздела:

Структура програми
  // Welcome.cpp #include <stdio.h> main() { printf("Hello, world"); return 0; } Перший рядок наведеної

Типи даних
  Type Size char, unsigned char, signed char 1 byte short, unsigned short 2 bytes

Константи
4.1. Цілі знакові константи Десяткові 23, -42, +1991 Мають тип int, якщо значення константи не перевищує максимально припустимого значен

Перерахування
Перерахування дозволяють використати імена замість числових значень. Перерахування можуть задавати ім’я типу. Перерахування можуть бути ініціалізовані певними (цілими) значеннями. Також може бути в

Цикл do - while
do оператор while(вираз);   Цикл do - while являє собою скорочений запис для   label: оператор; if(вираз) goto label;  

Оголошення
Оголошення визначає ім’я функції, тип значення, що повертається, і типи аргументів.   // Два аргументи типу double і повертає значення типу double. double Hypotenuse

Визначення
Визначення функції описує код, виконуваний під час виклику функції. Визначення функції може бути оголошено inline для оптимізації дуже маленьких функцій. Це оголошення не гарантує, що функція, огол

Покажчики
Покажчики – це змінні, які містять адресу іншої змінної або функції. Покажчики оголошуються за допомогою символу *.   int i, *pi = &i; // покажчик на int int *pp

Посилання
Посилання – це друге ім’я для іншої змінної. Посилання оголошуються за допомогою символу &. При оголошенні посилання повинні бути ініціалізовані (посилання може бути ініціалізоване лише один ра

Вектори
Вектори – це безперервні блоки пам’яті, що зберігають множину елементів того самого типу. Вони оголошуються за допомогою зазначення кількості елементів, що повинно бути позитивним цілим константним

Структури
Структури – це набір зв’язаної інформації, можливо, різних типів, об’єднаний в один об’єкт. Структури можуть мати ім’я, що у цьому випадку буде ім’ям типу.   struct Call

Конструктори
Конструктори ініціалізують об’єкт класу з необов’язковим списком аргументів. Аргументи, якщо вони використовуються, можуть мати значення за замовчуванням. Конструктори автоматично викликаю

Конструктори за замовчуванням
Конструктори за замовчуванням не мають аргументів (або всі аргументи мають значення за замовчуванням). Конструктор за замовчуванням потрібен, коли створюється масив об’єктів даного класу з використ

Деструктори
Деструктори виконують усі необхідні дії перед знищенням об’єкта. Деструктори автоматично викликаються компілятором: 1) при виході з області видимості; 2) при створенні тимчасових

Покажчики на члени класу
  Покажчики на члени класу вказують на нестатичні поля або методи (включаючи віртуальні) будь-якого об’єкта класу.   struct Point { int x, y;

Оголошення
Оголошення похідного класу вводить новий тип. Оголошення похідного класу встановлює обмеження доступу private, protected або public для членів свого базового класу. За замовчуванням встановлюється

Оголошення доступу
Оголошення доступу дає можливість знову зробити захищеними або відкритими захищені і відкриті члени закритого базового класу в похідному класі. Дозволяють зробити знову відкритими відкриті члени за

Стани помилки
Стани помилки підтримуються кожним із потоків. Стани помилки зберігаються як набір бітів: eofbit, failbit і badbit. Множинні стани одержуються за допомогою операції побітового АБО. int eof

Потокове виведення
Потокове виведення досягається при використанні змінних класів ostream або istream. Потокове виведення може застосовуватися з одним із визначених вихідних потоків або з вихідним потоком, що був виз

Потокове введення
Потокове введення досягається при використанні змінної класу istream або iostream. Може застосовуватися з визначеним вхідним потоком cin чи із вхідним потоком, визначеним користувачем.

Файлове виведення
Файлове виведення досягається при зв’язуванні вихідного потоку з файлом за допомогою змінної класу ofstream або fstream. Ці класи визначені у файлі заголовка fstream.h. Файлове виведення може викор

Файлове введення
Файлове введення досягається при зв’язуванні вхідного потоку з файлом за допомогою змінної класу ifstream або fstream. Ці класи визначені у файлі заголовка fstream.h. Файлове введення може використ

Стани форматування
Стани форматування управляють появою чисел при виконанні операції вставки у вихідний потік і форматуванням при виконанні операції зчитування із вхідного потоку. Стани форматування встановлюються за

Установка ширини поля
int width(int minimum); – установлює мінімальну ширину поля для даного розміру й повертає попередню ширину поля. Нуль означає відсутність мінімуму. Коли при вставці в потік або витягу з по

Установка системи числення
ios& dec(ios&); ios& oct(ios&); ios hex(ios&); ios& setbase(int); – змінює систему числення, використовувану для подання цілих чисел при

Хотите получать на электронную почту самые свежие новости?
Education Insider Sample
Подпишитесь на Нашу рассылку
Наша политика приватности обеспечивает 100% безопасность и анонимность Ваших E-Mail
Реклама
Соответствующий теме материал
  • Похожее
  • Популярное
  • Облако тегов
  • Здесь
  • Временно
  • Пусто
Теги