КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
Namespace CounterNameSpace 3 страница. cout << A_ob << A_ob;
cout << A_ob << A_ob; cout << A_ob+100; // Відображає число 124, оскільки тут виконується // перетворення об'єкта класу у значення типу int. cout << "\n"; A_ob = A_ob + A_ob; // Додавання двох об'єктів класу kooClass // Виконується без перетворення типу. cout << A_ob; // Відображає координати 3, 5, 7
getch (); return 0; } Внаслідок виконання цієї програми на моніторі буде відображено такі результати: 1,2, 3 2, 3, 4 3, 5, 7 Як підтверджують результати виконання цієї програми, якщо в такому виразі цілочисельного типу, як cout << A_ob+100, використовується об'єкт типу kooClass, то до цього об'єкта застосовується функція перетворення. У цьому випадку функція перетворення повертає значення 24, яке потім бере участь в операції додавання з числом 100. Але коли у перетворенні немає потреби, наприклад, під час обчислення виразу A_ob = A_ob + A_ob, то функція перетворення не викликається. Якщо функція перетворення створена, то вона викликатиметься скрізь, де потрібне перетворення, враховуючи ситуації, коли об'єкт передається функції як аргумент. Наприклад, якщо об'єкт класу kooClass передати стандартній функції abs (), то також буде викликано функцію, що виконує перетворення об'єкта типу kooClass у значення типу int, оскільки функція abs () повинна приймати аргумент цілочисельного типу. Необхідно пам'ятати! Для різних ситуацій можна створювати різні функції перетворення. Наприклад, можна визначити функції, які перетворять об'єкти типу kooClass у значення типу double або long, при цьому створені функції будуть застосовуватися автоматично. Функції перетворення дають змогу інтегрувати нові типи класів, що створюються програмістом, у С++-середовище програмування. Розділ 22. Введення в стандартну бібліотеку шаблонів Матеріал цього розділу містить інформацію про те, яку багато хто з програмістів вважає найважливішим доповненням у мові програмування C++ за останні роки. Йдеться про стандартну бібліотеку шаблонів (Standard Template Library – STL). Саме внесення бібліотеки STL у мову програмування C++ було основною подією, яка наполегливо обговорювалася у період стандартизації мови C++. Бібліотека STL надає користувачу шаблонні класи і функції загального призначення, які реалізують багато популярних і часто використовуваних алгоритмів і структур даних. Наприклад, вона містить підтримку векторів, списків, черг і стеків, а також визначає різні функції, які забезпечують до них доступ. Оскільки бібліотека STL складається з шаблонних класів, то алгоритми і структури даних можна застосовувати до даних практично будь-якого типу. Бібліотека STL – це набір шаблонних класів і функцій загального призначення. Бібліотека STL – це результат розроблення стандартного програмного забезпечення, який увібрав у себе одні з найскладніших засобів мови програмування C++. Щоб розуміти вміст бібліотеки STL і уміти ним користуватися, необхідно досконало засвоїти весь матеріал, викладений у попередніх розділах. Особливо добре потрібно орієнтуватися в шаблонах. Відверто кажучи, шаблонний синтаксис, який використовує бібліотека STL, може спочатку налякати програмістів-початківців, хоча він виглядає дещо складнішим, ніж є насправді. Незважаючи на те, що матеріал цього розділу є не надто важчим за будь-який інший, наведений у цьому навчальному посібнику, проте не варто засмучуватися від того, якщо щось на перший погляд Вам видасться незрозумілим. Трохи терпіння під час перегляду прикладів і певної уваги у процесі їх детального аналізу приведе до того, що незабаром Ви зрозумієте, як за незвичним синтаксисом ховається строга простота бібліотеки STL. STL – достатньо велика бібліотека, і всі її засоби неможливо викласти в одному розділі. Повний опис бібліотеки STL зі всіма її нюансами і методами програмування займає цілу книгу [2, 24, 31]. Мета представленого тут матеріалу – познайомити студентів з основними операціями, принципами проектування і основами STL-програмування. Засвоївши матеріал цього розділу, студент зможете самостійно легко вивчити іншу частину бібліотеки STL. У цьому розділі також описано ще один важливий клас C++ – клас string. Він призначений для визначення рядкового типу даних, який дає змогу обробляти символьні рядки подібно до того, як обробляються дані інших типів: за допомогою операторів. Клас string тісно пов'язаний з бібліотекою STL. 22.1. Огляд стандартної бібліотеки шаблонів Незважаючи на великий розмір стандартної бібліотеки шаблонів (STL) та інколи лякливий синтаксис, насправді її засоби достатньо легко використовувати, якщо зрозуміти, як вона побудована і з яких елементів складається. Тому, перш ніж переходити до перегляду прикладів, познайомимося з основними складовими бібліотеки STL. Ядро стандартної бібліотеки шаблонів містить три основні елементи: контейнери, алгоритми і ітератори. Вони працюють спільно один з іншим, надаючи тим самим користувачу готові розв'язки різних задач програмування. Контейнери – це об'єкти, які містять інші об'єкти. Існує декілька різних типів контейнерів. Наприклад, клас vector визначає динамічний масив, клас queue створює двосторонню чергу, а клас list забезпечує роботу з лінійним переліком. Ці контейнери називають послідовними контейнерами і є базовими в бібліотеці STL. Окрім базових, бібліотека STL визначає асоціативні контейнери, які дають змогу ефективно знаходити потрібні значення на основі заданих ключових значень (ключів). Наприклад, клас map забезпечує зберігання пар "ключ-значення" і надає можливість знаходити значення за заданим унікальним ключем. Кожен контейнерний клас визначає набір функцій, які можна застосовувати до даного контейнера. Наприклад, контейнер переліку містить функції, призначені для виконання вставки, видалення і об'єднання елементів. А стек містить функції, які дають змогу поміщати значення у стек і витягувати їх із стека. Алгоритми обробляють вміст контейнерів. Їх можливості містять засоби ініціалізації, сортування, пошуку і перетворення вмісту контейнерів. Багато алгоритмів працюють із заданим діапазоном елементів контейнера. Ітератори подібні до покажчиків. Ітератори – це об'єкти, які тою чи іншою мірою діють подібно до покажчиків. Вони дають змогу циклічно здійснювати запит до вмісту контейнера практично так само, як це робиться за допомогою покажчика під час циклічного запиту елементів масиву. Існує п'ять типів ітераторів. Табл. 22.1. Типи ітераторів
У загальному випадку ітератор, який має великі можливості доступу, можна використовувати замість ітератора з меншими можливостями. Наприклад, односпрямованим ітератором можна замінити вхідний ітератор. Ітератори обробляються аналогічно до покажчиків. Їх можна інкрементувати і декрементувати|. До них можна застосовувати оператор перейменування адреси *. Ітератори оголошуються за допомогою типу iterator, що визначається різними контейнерами. Бібліотека STL підтримує реверсивні ітератори, які є або двоспрямованими, або ітераторами довільного доступу, даючи змогу переміщатися по послідовності у зворотному порядку. Отже, якщо реверсивний ітератор вказує на кінець послідовності, то після інкрементування він вказуватиме на елемент, розташований перед кінцем послідовності. При посиланні на різні типи ітераторів у описах шаблонів у цьому навчальному посібнику буде використано такі терміни:
Бібліотека STL опирається не тільки на контейнери, алгоритми і ітератори, але і на інші стандартні компоненти. Основними з них є розподільники пам'яті, предикати і функції порівняння. Розподільник пам'яті керує виділенням пам'яті для контейнера. Кожен контейнер має свій розподільник пам'яті (allocator). Розподільники керують виділенням пам'яті для контейнера. Стандартний розподільник – це об'єкт класу allocator, але у разі потреби (у спеціалізованих додатках) можна визначати власні розподільники. Здебільшого стандартного розподільника є цілком достатньо для реалізації програмних задумів. Предикат повертає як результат значення ІСТИНА/ФАЛЬШ. Деякі алгоритми і контейнери використовують спеціальний тип функції, так званий предикат (predicate). Існує два варіанти предикатів: унарний і бінарний. Унарний предикат приймає один аргумент, а бінарний – два. Ці функції повертають значення ІСТИНА/ФАЛЬШ, але точні умови, які примусять їх повернути дійсне або помилкове значення, визначаються програмістом. В іншій частині цього розділу, коли знадобиться унарна функція-предикат, на це буде вказано за допомогою типу UnPred. У разі потреби використання бінарного предиката застосовуватиметься тип BinPred. У бінарному предикаті аргументи завжди розташовані у порядку перший, другий стосовно функції, яка викликає цей предикат. Як для унарного, так і для бінарного предикатів аргументи повинні містити значення, тип яких збігається з типом об'єктів, які зберігає цей контейнер. Функції порівняння порівнюють два елементи послідовності. Деякі алгоритми і класи використовують спеціальний тип бінарного предиката, який порівнює два елементи. Функції порівняння повертають значення true, якщо їх перший аргумент менший від другого. Функції порівняння ідентифікуються за допомогою типу Comp. Крім заголовків, потрібних різними класами STL, стандартна бібліотека C++ містить заголовки < utility > і < functional >, які забезпечують підтримку STL. Наприклад, у заголовку <utility> визначається шаблонний клас pair, який може зберігати пару значень. Будемо використовувати клас pair нижче у цьому розділі. Шаблони у заголовку < functional > дають змогу створювати об'єкти, які визначають функцію operator (). Ці об'єкти називаються об'єктами-функціями, і їх у багатьох випадках можна використовувати замість покажчиків на функції. Існує декілька вбудованих об'єктів-функцій, оголошених у заголовку < functional >. Наведемо тут деякі з них:
Можливо, найширше використовується об'єкт-функція less, який визначає, за яких умов один об'єкт менший від іншого. Об'єкти-функції можна використовувати замість реальних покажчиків на функції в алгоритмах бібліотеки STL, про які піде мова нижче. Використовуючи об'єкти-функції замість покажчиків на функції, бібліотека STL у деяких випадках генерує ефективніший програмний код. Матеріал цього розділу не передбачає використання об'єктів-функцій, і ми не застосовуватимемо їх безпосередньо. Детальний опис об'єктів-функцій можна знайти в книзі Герберта Шілдта " Полный справочник по C++" [27]. 22.2. Поняття про контейнерні класи Як ми вже зазначали вище, контейнери є об'єктами бібліотеки STL, основне призначення яких –зберігання даних. Контейнери, що визначаються в бібліотеці STL, представлено в табл. 22.1. У ній також вказано заголовки, які необхідно помістити у програму під час використання кожного контейнера. Незважаючи на те, що клас string також є контейнером, який дає змогу зберігати і обробляти символьні рядки, однак він у цю таблицю не включений і розглядається нижче у цьому розділі. Табл. 22.1. Контейнери, визначені в бібліотеці STL
Оскільки імена типів у оголошеннях шаблонних класів довільні, контейнерні класи оголошують typedef -версії цих типів, що конкретизує імена типів. Деякі з найбільш популярних typedef -імен мають таке призначення:
Оскільки в одному розділі неможливо розглянути всі контейнери, в наступних розділах ми представимо тільки три з них: vector, list і map. Якщо Ви зрозумієте, як працюють ці три контейнери, у Вас не буде проблем з використанням інших. 22.3. Робота з векторами Одним з контейнерів найширшого призначення є вектор. Клас vector підтримує динамічний масив, який у разі потреби може збільшувати свій розмір. Як уже зазначалося вище, у мові програмування C++ розмір масиву фіксується під час компілювання. І хоча це найефективніший спосіб реалізації масивів, він водночас є і тим самим обмежувачем, оскільки розмір масиву не можна змінювати у процесі виконання програми. Ця проблема розв'язується за допомогою вектора, який у міру потреби забезпечує виділення додаткового об'єму пам'яті. Незважаючи на те, що вектор – це динамічний масив, проте, для доступу до його елементів можна використовувати стандартне позначення індексації масивів. Вектори є динамічними масивами. Ось як виглядає шаблонна специфікація для класу vector: template < class myType, class Allocator = allocator <myType>> class vector У цьому записі myType – тип даних, що зберігається, а елемент Allocator означає розподільник пам'яті, який за замовчуванням використовує стандартний розподільник. Клас vector має такі конструктори: explicit vector (const Allocator & a = Allocator ()); explicit vector (size_type num|, const myType & val = myType(), const Allocator & a = Allocator ()); vector (const vector <myType, Allocator > & ob); template < class InIter > vector (InIter start, InIter end, const Allocator & a = Allocator ()); Перша форма конструктора призначена для створення порожнього вектора. Друга створює вектор, який містить num "елементів із значенням val ", причомузначення val можебути встановлено за замовчуванням. Третя форма дає змогу створити вектор, який містить ті самі елементи, що і заданий вектор ob. Четвертапризначена для створення вектора, який містить елементи у діапазоні, заданому параметрами-ітераторами start і end. Заради досягнення максимальної гнучкості та переносності будь-який об'єкт, який призначено для зберігання у векторі, повинен визначатися конструктором за замовчуванням. Окрім того, він повинен визначати операції "<" і "==". Деякі компілятори можуть зажадати визначення і інших операторів порівняння. (З причини існування різних реалізацій для отримання точної інформації про вимоги, що пред'являються Вашим компілятором, необхідно звернутися до документації, що додається до нього.) Всі вбудовані типи автоматично задовольняють ці вимоги. Незважаючи на те, що наведений вище синтаксис шаблону виглядає достатньо "масивним", у оголошенні вектора немає нічого складного. Розглянемо декілька прикладів: vector < int > iv; // Створення вектора нульової довжини для // зберігання int-значень. vector < char > cv(5); // Створення 5-елементного вектора для // зберігання char -значень. vector < char > cv(5, 'x'); // Ініціалізація 5-елементного // char -вектора. vector < int > iv2(iv); // Створення int-вектора на основі // int-вектора iv. Для класу vector визначено такі оператори порівняння: ==, <, <=,!=, > і >=. Для вектора також визначено оператор індексації "[]", який дає змогу отримати доступ до елементів вектора за допомогою стандартного запису з використанням індексів. Функції-члени, визначені у класі vector, перераховані в табл|. 22.2. Найважливішими з них є size (), begin (), end (), push_back (), insert () і erase (). Дуже корисна функція size (), яка повертає поточний розмір вектора, оскільки вона дає змогу визначити розмір вектора у процесі виконання програми. Необхідно пам'ятати! Вектори у разі потреби збільшують свій розмір, тому потрібно мати можливість визначати його величину під час роботи програми, а не тільки під час компілювання. Табл. 22.2. Функції-члени, визначені у класі vector
Функція begin () повертає ітератор, який вказує на початок вектора. Функція end () повертає ітератор, який вказує на кінець вектора. Як вже пояснювалося вище, ітератори подібні до покажчиків, і за допомогою функцій begin () і end () можна отримати ітератори початку і кінця вектора відповідно. Функція push_back () поміщає задане значення у кінець вектора. У разі потреби довжина вектора збільшується так, щоб він міг прийняти новий елемент. За допомогою функції insert () можна додавати елементи у середину вектора. Окрім того, вектор можна ініціалізувати. У будь-якому випадку, якщо вектор містить елементи, то для доступу до них і їх модифікації можна використовувати засіб індексації масивів. А за допомогою функції erase () можна видаляти елементи з вектора. Розглянемо короткий приклад, який ілюструє базову поведінку вектора. Код програми 22.1. Демонстрація базової поведінки вектора #include <iostream> // Для потокового введення-виведення #include <vector> // Для роботи контейнерним класом "Вектор" using namespace std; // Використання стандартного простору імен
int main () { vector < int > vek; // Створення вектора нульової довжини unsigned int i;
// Відображаємо початковий розмір вектора vek. cout << "Розмір = " << vek. size () << endl;
/* Поміщаємо значення у кінець вектора, і розмір вектора за потреби збільшуватиметься. */ for (i=0; i<10; i++) vek. push_back (i);
// Відображаємо поточний розмір вектора vek. cout << "Новий розмір = " << vek. size () << endl;
// Відображаємо вміст вектора. cout << "Поточний вміст:\n"; for (i=0; i<vek. size (); i++) cout << vek[i] << " "; cout << endl;
/* Поміщаємо у кінець вектора нові значення, і розмір вектора за потреби збільшуватиметься. */ for (i=0; i<10; i++) vek. push_back (i + 10);
// Відображаємо поточний розмір вектора vek. cout << "Новий розмір = " << vek. size () << endl;
// Відображаємо новий вміст вектора. cout << "Новий вміст:\n"; for (i=0; i<vek. size (); i++) cout << vek[i] << " "; cout << endl;
// Змінюємо вміст вектора. for (i=0; i<vek. size (); i++) vek[i] = vek[i] + vek[i];
// Відображаємо вміст вектора. cout << "Вміст подвоєно:\n"; for (i=0; i<vek. size (); i++) cout << vek[i] << " "; cout << endl;
Дата добавления: 2014-11-29; Просмотров: 504; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |