Дескриптори в c

template

inline Type * MP:: operator -> () const

Отже, після невеликого підігріву розумні покажчики перетворилися в ведучі. Тепер в нашому вариві з'являється ще один інгредієнт - дескриптори (handles) C ++. Не плутайте цей термін з дескрипторами, використовуваними в операційних системах Macintosh і Windows. Деяка схожість існує, але ідіома дескрипторів C ++ має власну унікальну семантику і набір правил.

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

template

MP operator -> () const

Безаргументний конструктор Н створює новий ведучий покажчик. Цей провідний покажчик, в свою чергу, створює вказується об'єкт. Існує другий конструктор, який отримує провідний покажчик і ініціалізує їм змінну ptr. Конструктор копій і оператор = за замовчуванням годяться, оскільки будь-якому провідному вказівником може відповідати кілька дескрипторів. Робота оператора -> заснована на рекурсивном алгоритмі, використовуваному компілятором: оператор -> дескриптора повертає провідний покажчик; потім оператор -> ведучого покажчика повертає покажчик Type * який є одним з базових типів компілятора.

Наведене рішення не назвеш витонченим - вкладені шаблони породжують плутанину, до того ж зовсім незрозуміло, коли і як видаляти провідні покажчики. Крім того, слід дозволити користувачеві безпосередньо створювати і знищувати провідні покажчики або ж укласти їх усередині дескрипторів так, як ми уклали вказуються об'єкти всередині провідних покажчиків? Невже ми працювали над вирішенням цих проблем для вказуються об'єктів лише потім, щоб зіткнутися з ними знову для провідних покажчиків? Терпіння - свого часу ми знайдемо відповідь на ці та багато інших питань.

Що ж виходить?

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

підрахунок об'єктів

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

class CountedStuff

static int current; public:

CountedStuff () CountedStuff (const CuntedStuff) CountedStuff operator = (const CountedStuff)

<> // Не змінювати лічильник для присвоювання

З цим прикладом ще можна повозитися і поліпшити його, але як би ви не старалися, доведеться змінювати код цільового класу - хоча б для того, щоб змусити його наслідувати від нашого класу. Тепер припустимо, що вказується об'єкт входить в комерційну бібліотеку. Прикро, так? Будь-які зміни небажані, а швидше за все, просто неможливі. Але ось на сцену виходить клас провідного покажчика.

template class CMP

static int current; Type * ptr;

CMP (const CMP cmp). ptr (new Type (* (mp.t))) CMP operator = (const CMP cmp)

if (this! = cmp)

ptr = new Type (* (cmp.ptr));

Тепер ведучий покажчик виконує всі підрахунки за вас. Він не потребує внесення змін до класу зазначених вище об'єкта. Цей шаблон може використовуватися для будь-якого класу за умови, що вам вдасться втиснути провідні покажчики між клієнтом і вказуються об'єктом. Навіть якщо ви не заперечуєте проти модифікації вихідного класу зазначених вище об'єкта, забезпечити такий рівень модульності без провідних покажчиків було б вкрай складно (наприклад, якби ви спробували діяти через базовий клас, то в результаті отримали б одну статичну змінну current на всі похідні класи).

Цей приклад тривіальний, але навіть він демонструє важливий принцип програмування на C ++, справедливість якого згодом стає очевидною: користуйтеся розумними покажчиками, навіть якщо спочатку здається, що вони не потрібні. Якщо програма написана для розумних покажчиків, всі зміни вносяться легко і швидко. Якщо ж вам доведеться переробляти готову програму і замінювати всі оператори * розумними покажчиками, приготуйтеся до нічних чувань.

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

Покажчики тільки для читання

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

- достатньо зробити операційну функцію operator -> () константної функцією класу.

template

ROMP operator = (const ROMP); const Type * operator -> () const;

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

Покажчики для читання / запису

У багатьох ситуаціях існує оптимальне представлення об'єкта, яке дійсно лише для операцій читання. Якщо клієнт хоче змінити об'єкт, уявлення доводиться змінювати.

Це було б легко зробити при наявності двох перевантажених версій оператора ->. одна з яких повертає Foo *. а інша - const Foo *. На жаль, різні повертаються типи не забезпечують унікальність сигнатур, тому при спробі оголосити два оператора -> компілятор від душі посміється. Програмісту доведеться заздалегідь викликати функцію, яка здійснює перехід від одного представлення до іншого.

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