Анимация
JavaScript
|
Главная Библионтека щищенного объектами sentry, малоэффективно. По возможности следует использовать соответствующий объект baslc streambuf. 1ользовательские форматные флаги При определении пользовательских операторов ввода-вывода часто бывает удобно определить для этих операторов специальные форматные флаги (вероятно, устанавливаемые при помощи соответствзтащих манипуляторов). Например, было бы неплохо, если бы приведенный выше оператор вывода дробей можно было настроить иа отделение пробелами числителя и знаменателя от символа /. Объекты потоков данных предоставляют такую возможность - в них предусмотрен механизм связывания данных с потоком. Он позволяет задать нужные значения (например, при помощи манипулятора) и прочитать их позднее. В классе los base определены две функции iword() и pword(), которые при вызове получают индекс типа Int и возвращают по нему соответствующее значение long8i и vold*8i. Предполагается, что iword() и pword() обращаются к объектам long или void* в массиве произвольного размера, хранящемся в объекте потока данных. Форматные флаги, сохраняемые для потока, располагаются по одному и тому же индексу для всех потоков. Статическая функция ха11ос() класса ios base используется для получения индекса, который еще не применялся для этой цели. В исходном состоянии объекты, доступ к которым осзществляется функциями IwordO и pword(), равны 0. Это значение может интерпретироваться и как представление форматирования по умолчанию, и как признак того, что данные еще не инициализировались. Пример: Получение индекса для новых данных ostream static const int iwordjndex - std: :los base: :хаПос(): Определение манипулятора для модификации этих данных std::ostream& fract1on spaces (std::ostream& strm) strni.iword(1word 1ndex) - true: return strm: std::ostream& operator« (std::ostream& strm. const Fractions f) { /* Запросить данные у ostream * - true: использовать пробелы между числителем и знаменателем * - false: выводить без пробелов */ if (stem.iworddwordjndex)) { strm « f.numeratorO « " / " « f.denominatorO; else { strm « f.numeratorO « "/" « f.denominatorO: return strm; В этом примере используется упрощенный подход к реализации оператора вывода, поскольку его основная цель - демонстрация функции Iword(). Форматный флаг считается логическим признаком, определяющим необходимость вывода пробелов между числителем и знаменателем. В первой строке функция los base;:xalloc() возвращает индекс, который может использоваться для хранения форматного флага. Результат вызова сохраняется в константе, так как это значение не модифицируется. Функция fractlon spaces() представляет собой манипулятор для установки значения Int, хранящегося по индексу Iwordjndex в целочисленном массиве, связанном с потоком данных strm. Оператор вывода получает это значение и выводит дробь в соответствии с состоянием флага. Если флаг равен false, по умолчанию дробь выводится без пробелов, а если нет - символ / окружается двумя пробелами. Функции IwordO и pwordO возвращают ссылки на Int или void*. Эти ссылки остаются действительными только до следующего вызова lword() или pword() с соответствующим объектом потока данных нли до уничтожения объекта потока. Обычно результаты lword() и pwordQ сохраняться не должны. Предполагается, что доступ происходит достаточно быстро, хотя представление данных в виде массива не гарантировано. Функция copyfmtO копирует всю форматирующую информацию (см. с. 591), в том числе и массивы, с которыми работают функции lword() и pword(). Это может вызвать проблемы для объектов, сохраняемых в контексте потока данных при помощи pword(). Например, если значение представляет собой адрес объекта, то вместо объекта будет скопирован только адрес. Как следствие, смена формата в одном потоке данных будет распространяться на другие потоки. Также может быть желательно, чтобы объект, ассоциированный с потоком данных функцией pword(), уничтожался при уничтожении потока. Следовательно, для таких объектов желательно реализовать «глубокое» копирование вместо «поверхностного». Для подобных целей (например, реализации глубокого копирования в случае необходимости или удаления объекта при уничтожении потока данных) в los base определен механизм обратного вызова. Функция reglster callback() регистрирует функцию, вызываемую при выполнении определенных условий для объекта ios base. Функция определяется следующим образом: namespace std { class los base { public: Разновидности событий обратного вызова enum event { erase event. imbue event. copyfmt event }: Тип функции обратного вызова typedef void (*"event callback) (event e. 1os base& strm. int arg): Регистрация функций обратного вызова void register callback (event callback cb. int arg): } Функция reglster callback() получает два аргумента: указатель на функцию и число Int. Аргумент Int передается в третьем аргументе при вызове зарегистрированной функции. Например, он может использоваться для идентификации индекса pword(), то есть определять обрабатываемый элемент массива. Аргумент strm, передаваемый функции обратного вызова, содержит объект los base, обратившийся к этой функции. Аргумент е определяет причину вызова, его допустимые значения перечислены в табл. 13.40. Таблица 13.40. Причины обратного вызова
При вызове для объекта функции copyfmt() функции обратного вызова вызываются дважды. Еще до начала копирования они вызываются с аргументом erase event для выполнения необходимой зачистки (например, удаления объектов, хранящихся в массиве pwordO). После копирования данных форматирования функции обратного вызова вызываются снова, на этот раз - с аргументом сору event. Например, этот проход может использоваться для организации глубокого копирования объектов, хранящихся в массиве pword(). Обратите внимание: вместе с данными форматирования копируются и функции обратного вызова, а исходный список зарегистрированных фзкций удаляется. Следовательно, при втором проходе будут вызваны только что скопированные функции. Механизм обратного вызова чрезвычайно примитивен. Он не позволяет отменять регистрацию функций обратного вызова (не считая вызова copyfmt() с аргументом, не имеющим зарегистрированных функций). Кроме того, повторная регистрация функции обратного вызова даже с тем же аргументом приведет к повторному вызову. Тем не менее библиотека гарантирует, что функции будут вызваны в порядке, обратном порядку их регистрации. Это сделано для того, чтобы функция обратного вызова, зарегистрированная из другой функции, не вызывалась до следующего срабатывания функций обратного вызова. 1равила построения пользовательских >ператоров ввода-вывода Ниже перечислены некоторые правила, которые должны соблюдаться в пользовательских реализациях операторов ввода-вывода. Эти правила продиктованы типичным поведением стандартных операторов. О Выходной формат должен допускать определение оператора ввода, читающего данные без потери информации. В некоторых случаях - особенно для строк - эта задача практически невыполнима из-за проблем с пробелами. Пробел внутри строки невозможно отличить от пробела, разделяющего две строки. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 [ 205 ] 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |