Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Либерти Джесс. Освой самостоятельно С++ за 21 день. - royallib.ru.rtf
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
2.55 Mб
Скачать

День 19 Контрольные вопросы

1. Какова разница между шаблоном и макросом?

Шаблоны являются средствами программирования языка C++, поддерживающими контроль за соответствием типов данных. Макросы выполняются препроцессором и не обеспечивают безопасности работы с типами.

2. В чем состоит отличие параметра шаблона от параметра функции?

Параметр шаблона используется для создания экземпляра шаблона для каждого типа. Если создать шесть экземпляров шаблонов, то будут созданы шесть различных классов или функций. Параметры функций определяют, какие данные передаются в функцию при ее вызове, но не могут использоваться для создания разных экземпляров одной функции.

3. Чем отличается обычный дружественный шаблонный класс от дружественного шаблонного класса, специализированного по типу?

Обычный дружественный шаблонный класс создает одну функцию для всех экземпляров параметризованного класса, а специализированный по типу дружественный шаблонный класс создает специализированные по типу экземпляры функции для каждого экземпляра параметризованного класса.

4. Можно ли обеспечить особое выполнение для определенного экземпляра шаблона?

Да. Создайте для конкретного экземпляра шаблона функцию, специализированную по типу. Чтобы изменить выполнение, например, для массивов целых чисел, помимо функции Array<t>::SomeFunction(), создайте также функцию Array<int>::SomeFunction().

5. Сколько создается статических переменных-членов, если поместить один статический член в определение класса шаблона?

По одной для каждого экземпляра класса.

6. Что представляют собой итераторы?

Это обобщенные указатели. Итератор можно инкрементировать, чтобы он указывал на следующий узел в последовательности. К нему также можно применить операцию разыменования, чтобы возвратить узел, на который он указывает.

7. Что такое объект функции?

Это экземпляр класса, в котором определен перегруженный оператор вызова функции (). Объект функции можно также использовать как обычную функцию.

Упражнения

1. Создайте шаблон на основе данного класса List:

class List

{

   public:

      List():head(0),tail(0), tbeCount(0) { }

      virtual ~List();

      void insert( int value );

      void append( int value );

      int is_present( int value ) const;

      int is_empty() const { return head == 0: }

      int count() const { return theCount; }

   private:

      class ListCell

      {

         public:

            ListCell(int value, ListCell *cell = ):val(value),next(cell){ }

            int val;

            ListCell *next;

      };

      ListCell *head;

      ListCell *tail;

      int theCount;

};

Вот один из способов выполнения этого шаблона:

template <class Type>

class List

{

   public:

      List():head(0),tail(0),theCount(0) { }

      virtual ~List();

      void insert( Type value );

      void append( Type value );

      int is_present( Type value ) const;

      int is_empty() const { return head == 0; }

      int count() const { return theCount; }

   private:

      class ListCell

      {

         public:

            ListCell(Type value, ListCell *cell = O):val(value),next(cell) { }

            Type val;

            ListCell *next;

      };

      ListCell *head;

      ListCell *tail;

      int theCount;

};

2. Напишите выполнение обычной (не шаблонной) версии класса List.

void List::insert(int value)

{

   ListCell *pt = new ListCell( value, head );

   assert (pt ! = 0);

   // эта строка добавляется для обработки хвостового узла

   if ( head -= 0 ) tail = pt,

      head = pt;

   theCount++;

}

void List::append( int value )

{

   ListCell *pt = new ListCell( value );

   if ( head — 0 )

      head = pt;

   else

      tail->next = pt:

   tail = pt;

   theCount++;

}

int List::is_present( int value ) const

{

   if ( head == 0 )

      return 0;

   if ( head->val — value || tail->val == value )

      return 1;

   ListCell *pt = head->next;

   for (; pt != tail; pt = pt->next)

      if ( pt->val == value )

         return 1;

   return 0;

}

3. Напишите шаблонный вариант выполнения.

template <class Type>

List<Type>::~List()

{

   ListCell *pt = head;

   while ( pt )

   {

      ListCell *tmp = pt;

      pt = pt->next;

      delete tmp;

   }

   head = tail = 0;

}

template <class Type>

void List<Type>::insert(Type value)

{

   ListCell *pt = new ListCell( value, head );

   assert (pt ! = 0);

   // эта строка добавляется для обработки хвостового узла

   if ( head == 0 )

      tail = pt;

   head = pt;

   theCount++;

}

template <class Type>

void List<Type>::append( Type value )

{

   ListCell *pt = new ListCell( value );

   if ( head == 0 )

      head = pt;

   else

      tail->next = pt;

   tail = pt;

   theCount++;

}

template <class Type>

int List<Type>::is_present( Type value ) const

{

   if ( head == 0 )

      return 0;

   if ( head->val == value || tail->val == value )

      return 1;

   ListCell *pt = head->next;

   for (; pt != tail; pt = pt->next)

      if ( pt->val — value )

         return 1;

   return 0;

}

4. Объявите три списка объектов: типа Strings, типа Cat и типа int.

List<String> string_list;

List<Cat> Cat_List;

List<int> int_List;

5. Жучки: что неправильно в приведенном ниже программном коде? (Предположите, что определяется шаблон класса List, а Cat — это класс, определенный выше в данной книге.)

List<Cat> Cat_List;

Cat Felix;

CatList.append( Felix );

cout << "Felix is " << ( Cat_List.is_present( Felix ) ) ? "" : "not " << "present\n";

ПОДСКАЗКА (поскольку задание не из самых легких): подумайте, чем тип Cat отличается от типа int.

В классе Cat не определен оператор operator==. Все операции, в которых сравниваются значения членов класса iist, таких как is_present, будут вызывать ошибку компиляции. Для уменьшения вероятности возникновения таких ошибок перед объявлением шаблона поместите обширный комментарий, в котором должно быть указано, какие операторы следует определить в классе для успешного выполнения всех его методов.

6. Объявите дружественный оператор operator== для класса List.

friend int operator==( const Type& lhs, const Type& rhs );

7. Напишите выполнение дружественного оператора operator== для класса List.

template <class Type>

int List<Type>::operator==( const Type& lhs, const Type& rhs )

{

   // сначала сравниваем размеры списков

   if ( lhs.theCount != rhs.theCount )

      return 0; // списки различны

   ListCell *lh = lhs.head;

   ListCell *rh = rhs.head;

   for(; lh != 0; lh = lh.next. rh = rh.next )

      if ( lh.value != rh.value )

         return 0;

   return 1; // если они не различны, то совпадают

}

8. Грешитли оператор operator== той же проблемой, которая существует в упражнении 5?

Да. Поскольку сравнение массива включает сравнение элементов, то для элементов также должен быть определен оператор operator!=.

9. Напишите выполнение функции шаблона, осуществляющей операцию обмена данными, в результате чего две переменные должны обменяться содержимым.

// шаблон swap:

// должен иметь оператор присваивания и конструктор-копировщик, определенные для

класса Туре,

template <class Type>

void swap( Type& lhs, Type& rhs)

{

   Type temp( lhs );

   lhs = rhs;

   rhs = temp;

}

10. Напишите выполнение класса SchoolClass, показанного в листинге 19.8, как списка. Для добавления в список четырех студентов используйте функцию push_back(). Затем пройдитесь по полученному списку и увеличьте возраст каждого студента на один год.

#include <list>

template<class T, class A>

void ShowList(const iist<T, А>& aList); // отображаем свойства вектора

typedef list<Student> SchoolClass;

int main()

{

   Student Harry("Harry". 18);

   Student Sally("Sally", 15);

   Student Bill( "Bill", 17);

   Student Peter("Peter", 16);

   SchoolClass GrowingClass;

   GrowingClass.push_back(Harry);

   GrowingClass.push_back(Sally);

   GrowingClass.push_back(Bill);

   GrowingClass.push_back(Peter);

   ShowList(GrowingClass);

   cout << "Один год спустя:\n";

   for (SchoolClass::iterator i = GrowingClass.begin(); i != GrowingClass.end(); ++i)

      i->SetAge(i->GetAge() + 1);

   ShowList(GrowingClass);

   return 0;

}

//

// Отображаем свойства списка

//

template<class T, class A>

void ShowList(const list<T, А>& aList)

{

   for (list<T, A>::const_iterator ci = aList.begin(); ci != aList.end(); ++ci)

      cout << *ci << "\n";

   cout << endl;

}

11. Измените код из упражнение 10 таким образом, чтобы для отображения данных о каждом студенте использовался объект функции.

#include <algorithm>

template<class T>

class Print

{

   public:

      void operator()(const T& t)

      {

         cout << t << "\n";

      }

}

template<class T, class A>

void ShowList(const list<T, A>& aList)

{

   Print<Student> PrintStudent;

   for_each(aList.begin(), aList.end().PrintStudent):

     cout << endl;

}