Да се реализира шаблонен клас Dictionary с два типови параметъра T и U, който представя речник, съдържащ ключове от тип T и обекти от тип U. Представянето да бъде с два масива - един с обекти от T и един с обекти от U. Да се реализират:
  • голяма четворка
  • добавяне на ключ и обект
  • търсене на обект по ключ
  • отпечатване на речника
  • сортиране на обектите в речника по ключове
  • разширяване на речника при изчерпване на капацитета
Да се създаде абстрактен клас Contact, който съдържа функции за връщане на име (name), телефонен номер (phone) и идентификатор (id).

Да се създаде клас ContactBook, който представя бележник с контакти като сбор от три речника, чиито ключове са съответно име, телефонен номер и идентификатор, а стойностите са указатели към контакти (Contact*). Внимание: ContactBook няма да се грижи за създаването и унищожаването на контакти, а само за тяхното поддържане. Затова не се налага да пишем голяма четворка. За този клас да се реализират:
  • добавяне на контакт
  • намиране на контакт по даден критерий
  • отпечатване на книгата с контакти подредена по даден критерий
От това, че Dictionary е шаблон (template) произлизат два проблема:
  1. отпечатването на Dictionary използва операцията << за типовете T и U, обаче типът U за ContactBook винаги е Contact*, затова отпечатването просто ще изведе стойността на указателя, а не контакта, както очакваме.
  2. търсенето по ключ ще работи правилно за ключове които са числа (като телефонен номер), но не и за ключове които са стрингове (например име). Същото важи и за сравнението при сортиране
Тези проблеми могат да се решат например по следния начин:
  1. Дефинира се операторна функция (външна за класа, не е член-функция)
    ostream& operator<< (ostream& os, Contact* pc)
    {
    pc -> print(os);
    return os;
    }
    Хубавото на този подход е, че имаме динамично свързване при извикването на print, което означава че ще се извика подходящата функция за отпечатване в производния клас.
  2. Дефинира се клас String, който се държи като char*, но предефинира операторите == и < по следния начин:
    class String
    {
    char* cs;
    public:
    /* следните три дефиниции карат класа String да се държи точно като char* като дефинира двупосочна конверсия между двата типа */
    String() {}
    String(char* _cs) { cs = _cs; }
    operator char*() { return cs; }
    /* сега дефинираме оператори за сравнение */
    bool operator==(String const& s) const
    { return strcmp(cs, s.cs) == 0; }
    bool operator<(String const& s) const
    { return strcmp(cs, s.cs) < 0; }
    };
    Единственото, което остава да променим е типът T на съответните речници за търсене по име и идентификатор в ContactBook да са String вместо char*.
Last modified: Saturday, 12 November 2011, 5:38 PM