Рейтинговые книги
Читем онлайн Освой самостоятельно С++ за 21 день. - Джесс Либерти

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 129 130 131 132 133 134 135 136 137 ... 170

В конце программы созданные массивы удаляются, а при вызове их деструкторов также удаляются и все их объекты. Процесс удаления отражен в строке 16 результатов выполнения программы.

При следующем выполнении программы (результаты показаны в строках 18-43) были закомментированы несколько строк программного кода (со 114 по 118), содержащие специализированный конструктор класса Array. В результате при выполнении программы для создания массива объектов Animal вызывается конструктор шаблона, показанныйвстроках74-81.

Это приводит к созданию временных объектов Animal для каждого члена массива (строки программы 79 и 80), что отражается в строках 18-20 результатов выполнения программы.

Во всех остальных аспектах, результаты выполнения двух вариантов программы, как и следовало ожидать, идентичны.

Статические члены и шаблоны

В шаблоне можно объявлять статические переменные-члены. В результате каждый экземпляр шаблона будет иметь собственный набор статических данных. Например, если добавить статическую переменную-член в шаблон Array (например, для подсчета количества созданных массивов), то в рассмотренной выше программе будут созданы две статические переменные-члена: одна для подсчета массивов объектов типа Animal и другая для массивов целых чисел. Добавление статической переменной-члена и статической функции в шаблон Array показано в листинге 19.7.

Листинг 19.7. Использование статических переменных-членов и функций-членов с шаблонам

1: #include <iostream.h>

2:

3: const int DefaultSize = 3;

4:

5: // Обычный класс, из объектов которого создается массив

6: class Animal

7: {

8:    public:

9:       // конструкторы

10:      Animal(int);

11:      Animal();

12:      ~Animal();

13:

14:      // методы доступа

15:      int GetWeight() const { return itsWeight: }

16:      void SetWeight(int theWeight) { itsWeight = theWeight }

17:

18:      // дружественные операторы

19:      friend ostream& operator<< (ostream&, const Animal&);

20:

21:   private:

22:      int itsWeight;

23: };

24:

25: // оператор вывода обьектов типа Anlmal

26: ostream& operator<<

27:    (ostream& theStream, const Animal& theAnimal)

28: {

29:    theStream << theAnimal.GetWeight();

30:    return theStream;

31: }

32:

33: Animal::Animal(int weight):

34: itsWeight(weight)

35: {

36:    //cout << "animal(int) ";

37: }

38:

39: Animal::Animal():

40: itsWeight(0)

41: {

42:    // cout << "animal() ";

43: }

44:

45: Animal::~Animal()

46: {

47:    // cout << "Destroyed an animal...";

48: }

49:

50: template <class T> // объявляем шаблон и параметр

51: class Array // параметризованный класс

52: {

53:    public:

54:       // конструкторы

55:       Array(int itsSize = DefaultSize);

56:       Array(const Array &rhs);

57:       ~Array() { delete [] рТуре; itsNumberArrays-; }

58:

59:       // операторы

60:       Array& operator=(const Array&);

61:       T& operator[](int offSet) { return pType[offSet]; }

62:       const T& operator[](int offSet) const

63:          { return pType[offSet]; }

64:       // аксессоры

65:       int GetSize() const { return itsSize; }

66:       static int GetNumberArrays() { return itsNumberArrays; }

67:

68:       // функция-друг

69:       friend ostream& operator<< (ostream&, const Array<T>&); 70:

71:    private:

72:       T *pType;

73:       int itsSize;

74:       static int itsNumberArrays;

75: };

76:

77: template <class T>

78: int Array<T>::itsNumberArrays = 0;

79:

80: template <class T>

81: Array<T>::Array(int size = DefaultSize):

82: itsSize(size)

83: {

84:    pType = new T[size];

85:    for (int i = 0; i<size; i++)

86:       pType[i] = (T)0;

87:    itsNumberArrays++;

88: }

89:

90: template <class T>

91: Array<T>& Array<T>::operator=(const Array &rhs)

92: {

93:    if (this == &rhs)

94:       return *this;

95:    delete [] pType;

96:    itsSize = rhs.GetSize();

97:    pType = new T[itsSize];

98:    for (int i = 0; i<itsSize; i++)

99:       pType[i] = rhs[i];

100: }

101:

102: template <class T>

103: Array<T>::Array(const Array &rhs)

104: {

105:    itsSize = rhs.GetSize();

106:    pType = new T[itsSize];

107:    for (int i = 0; i<itsSize; i++)

108:       pType[i] = rhs[i];

109:    itsNumberArrays++;

110: }

111:

112:

113: template <class T>

114: ostream& operator<< (ostream& output, const Array<T>& theArray)

115: {

116:    for (int i = 0: i<theArray.GetSize(); i++)

117:       output'<< "[" << i << "] " << theArray[i] << endl;

118:    return output;

119: }

120:

121:

122:

123: int main()

124: {

125:

126:    cout << Array<int>::GetNumberArrays() << " integer arraysn";

127:    cout << Array<Animal>::GetNumberArrays();

128:    cout << " animal arraysnn";

129:    Array<int> intArray;

130:    Array<Animal> animalArray;

131:

132:    cout << intArray.GetNumberArrays() << " integer arraysn";

133:    cout << animalArray.GetNumberArrays();

134:    cout << " animal arraysnn";

135:

136:    Array<int> *pIntArray = new Array<int>;

137:

138:    cout << Array<int>::GetNumberArrays() << " integer arraysn";

139:    cout << Array<Animal>::GetNumberArrays();

140:    cout << " animal arraysnn";

141:

142:    delete pIntArray;

143:

144:    cout << Array<int>::GetNumberArrays() << " integer arraysn";

145:    cout << Array<Animal>::GetNumberArrays();

146:    cout << " animal arraysnn";

147:    return 0;

148: }

Результат:

0 integer arrays

0 animal arrays

1 integer arrays

1 animal arrays

2 integer arrays

1 animal arrays

1 integer arrays

1 animal arrays

Анализ: Для экономии места в листинге опущено объявление класса Animal. В класс Array добавлена статическая переменная itsNumberArrays (в строке 74), а поскольку эта перемененная объявляется в разделе закрытых членов, в строке 66 добавлен открытый статический метод доступа GetNumberArrays().

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

Доступ к статической переменной, заданной в шаблоне, можно получить так же, как и при работе со статическими переменными-членами обычного класса: с помощью метода доступа, вызванного для объекта класса, как показано в строках 132 и 133, или явным обращением к переменной класса, как показано в строках 126 и 127. Обратите внимание, что при обращении к статической переменной-члену необходимо указать тип массива, так как для каждого типа будет создана своя статическая переменная-член.

Рекомендуется:Используйте статические члены в шаблонах. Специализируйте выполнение шаблона путем замещения функций шаблона для разных типов. Указывайте параметр типа при вызове статических функций шаблона, чтобы получить доступ к функции требуемого типа.

Стандартная библиотека шаблонов

Отличительной чертой новой версии языка C++ является принятие стандартной библиотеки шаблонов (Standard Template Library — STL). Все основные разработчики компиляторов теперь предлагают библиотеку STL как составную часть своих программных продуктов. STL — это библиотека классов контейнеров, базирующихся на шаблонах. Она включает векторы, списки, очереди и стеки, а также ряд таких общих алгоритмов, как сортировка и поиск.

Цель включения библиотеки STL состоит в том, чтобы избавить вас от очередного изобретения колеса и при разработке выполнить за вас рутинные общепринятые процессы. Библиотека STL оттестирована и отлажена, отличается высокой эффективностью и не требует дополнительных затрат. Важнее всего то, что библиотеку STL можно использовать многократно для разработки собственных приложений. Необходимо только один раз разобраться в принципах использования библиотеки STL и классов- контейнеров.

Контейнеры

Контейнер — это объект, который содержит другие объекты. Стандартная библиотека C++ предоставляет ряд классов-контейнеров, являющихся мощными инструментальными средствами, которые помогают разработчикам C++ решать наиболее общие задачи программирования. Среди классов контейнеров стандартной библиотеки шаблонов (STL) различаются два типа: последовательные и ассоциативные. Последовательные контейнеры предназначены для обеспечения последовательного или произвольного доступа к своим членам, или элементам. Ассоциативные контейнеры оптимизированы таким образом, чтобы получать доступ к своим элементам по ключевым значениям. Подобно другим компонентам стандартной библиотеки C++, библиотека STL совместима с различными операционными системами. Все классы-контейнеры библиотеки STL определены в пространстве имен std.

Последовательные контейнеры

Такие контейнеры стандартной библиотеки шаблонов обеспечивают эффективный последовательный доступ к списку объектов. Стандартная библиотека C++ предоставляет три вида последовательных контейнеров: векторы, списки и двухсторонние очереди.

1 ... 129 130 131 132 133 134 135 136 137 ... 170
На этой странице вы можете бесплатно читать книгу Освой самостоятельно С++ за 21 день. - Джесс Либерти бесплатно.

Оставить комментарий