Qt:Документация 4.3.2/qt4-tulip
Материал из Wiki.crossplatform.ru
Внимание: Актуальная версия перевода документации находится здесь |
__NOTOC__
Главная · Все классы · Основные классы · Классы по группам · Модули · Функции |
[Предыдущая: Что нового в Qt 4 ] [ Начало ] [Следующая: Структура Interview ]
Содержание |
Классы-контейнеры Tulip
Qt 4 представляет новый набор контейнеров, заменяющих старый контейнер указателей QCollection и более новый, основанный на значениях QTL.
Общий Обзор
Контейнеры Tulip заменяют собой QTL контейнеры Qt 3 (QValueList, QValueVector, QMap), но имеют ряд преимуществ:
- Контейнеры предоставляют новый улучшенный и более защищенный от ошибок синтаксис, чем STL, подобный Java-итераторам. (Итераторы стиля STL остаются как облегченная STL-совместимая альтернатива.)
- Контейтеры оптимизированы для минимизации набираемого кода.
- Пустой контейнер практически не занимает памяти, так как память требуется только для хранения указателя.
- Контейнеры вполне защищены, их можно свободно копировать даже между потоками без дополнительных формальностей. Они не требуют использования QDeepCopy.
Tulip предоставляет следующий набор контейнеров: QList, QLinkedList, QVector, QStack и QQueue. В большинстве приложений лучше всего использовать QList. Класс реализован в виде списка-массива, что позволяет быстро добавлять в начало и в конец. Если вам нужен настоящий связанный список, то используйте QLinkedList; если вы хотите размещать записи в памяти рядом, обратите внимание на QVector. QStack и QQueue удобно предоставляют семантику FIFO и LIFO.
Tulip также предоставляет следующие ассоциативные контейнеры: QMap, QMultiMap, QHash, QMultiHash и QSet. "Multi" контейнеры поддерживают ассоциирование нескольких значений с одним ключем. "Hash" контейнеры предоставляют быстрый доступ с использованием хеш функции для бинарного поиска в отсотированном наборе.
Контейнеры Tulip поддерживают конструкцию foreach - Qt-специфичную добавку к языку C++, использующую стандартный C++ препроцессор. Её синтаксис:
foreach (переменная, контейнер) выражение;
Пример:
QList<QString> list; ... foreach (QString str, list) cout << str.ascii() << endl;
Переменная-итератор может быть объявлена и вне цикла. Пример:
QString str; foreach (str, list) cout << str.ascii() << endl;
Как и for, foreach поддерживает, break, continue и вложенность. Qt делает копию контейнера перед входом в цикл. Если вы измените контейнер во время выполнения цикла, то в цикле этого не будет заметно.
Для получения детальной информации о новых контейнерах смотрите обзоры Основные контейнеры и Основные алгоритмы.
В добавок к новым контейнерам значительно много усилий было вложено в QByteArray и QString. В Qt 3 класс QCString был подобен QByteArray. Новый QByteArray автоматически добавляет разделитель '\0' после последнего символа. Например, массив байтов размера 5 содержащий "abcde" имеет нулевой байт в позиции 5 (один байт пополнительно). Это устраняет все проблемы, возникавшие в Qt 3 при взаимных преобразованиях между QByteArray и QCString.
Во избежание ошибок QByteArray::data() никогда не возвращает нулевой указатель. Кроме того, ликвидировано различие между нулевым указателем и указателем на пустую строку. К примеру QByteArray() == QByteArray("") и QString() == QString("").
Примеры
Первая группа примеров показывает, как использовать итераторы в стиле Java. Основное различие между итераторами стиля Java и стиля STL заключается в том, что итератор стиля Java указывает на точку между записями (либо перед первой записью, либо после последней), тогда как итератор стиля STL указывает на запись (либо на "место после последней записи"). Основное преимущество итераторов в стиле Java является то, что перебор записей вперед и назад - действия симметричные.
Перебор записей в контейнере с помощью итераторов стиля Java:
// вперёд // назад QList<QString> list; QList<QString> list; ... ... QListIterator<QString> i(list); QListIterator<QString> i(list); while (i.hasNext()) i.toBack(); cout << i.next().ascii() << endl; while (i.hasPrev()) cout << i.prev().ascii() << endl;
Изменение записей с помощью итераторов стиля Java:
// вперёд // назад QMutableListIterator<int> i(list); QMutableListIterator<int> i(list); while (i.hasNext()) i.toBack(); if (i.next() > 128) while (i.hasPrev()) i.setValue(128); if (i.prev() > 128) i.setValue(128);
Удаление записей с помощью итераторов стиля Java:
// вперёд // назад QMutableListIterator<int> i(list); QMutableListIterator<int> i(list); while (i.hasNext()) i.toBack(); if (i.next() % 2 != 0) while (i.hasPrev()) i.remove(); if (i.prev() % 2 != 0) i.remove();
Специфика перебора записей с использованием итераторов в стиле STL и в стиле Java:
// стиль STL // стиль Java QMap<int, QWidget *>::const_iterator i; QMapIterator<int, QWidget *> i(map); for (i = map.begin(); i != map.end(); ++i) while (i.findNext(widget)) if (i.value() == widget) cout << "Found widget " << widget cout << "Found widget " << widget << " under key " << " under key " << i.key() << endl; << i.key() << endl;
Модификация и удаление записей с использованием итераторов в стиле STL и в стиле Java:
// стиль STL // стиль Java QList<int>::iterator i = list.begin(); QMutableListIterator<int> i(list); while (i != list.end()) { while (i.hasNext()) { if (*i == 0) { int val = i.next(); i = list.erase(i); if (val < 0) } else { i.setValue(-val); if (*i < 0) else if (val == 0) *i = -*i; i.remove(); ++i; } } }
Следующая группа примеров демонстрирует API для непосредственной раборы с классами-контейнерами. API для работы с классами-контейнерами похож на классы QTL в Qt 3, но лучше во многих отношениях.
Перебор записей в QList с использованием индекса (подобный способ доступа является достаточно быстрым, даже для больших списков, т.к. QList реализован в виде списка-массива):
QList<double> list; ... for (int i = 0; i < list.size(); ++i) { if (list[i] < 0.0) list[i] = 0.0; }
Возвращение из словаря использует значение по умолчанию, если элемент с данным ключем отсутствует:
QMap<QString, int> map; ... map.value("TIMEOUT", 30); // возвращает 30, если "TIMEOUT" не определён в словаре
Получение всех значений, ассоциированных с ключем в QMultiMap or QMultiHash:
QMultiMap<QString, int> map; ... QList<int> values = map.values("TIMEOUT");
Сравнение с Qt 3
Контейнеры Tulip содержат значения. Если вы хотите использовать список в котором каждое значение - это QWidget *, используйте QList< QWidget *>.
Новые контейнеры не поддерживают автоудаления. Мы обраружили, что на практике, единственным случаем, гда нужно автоудаление является ситуация, где в контейнере содержатся значения, а не указатели (например, QList<int>, а не QList<int *>). Если вы хотите удалить все элементы, хранящиеся в контейнере, используйте qDeleteAll().
Если вы привыкли использовать QValueList в Qt 3, то в Qt 4 можете с легкостью заменить его на QList или QLinkedList. В большинстве случаев лучшим выбором является QList: как правило, он быстрее, требует меньшего кодирования и меньше памяти. Однако итераторы при работе с QLinkedList обеспечивают большую надежность, и только QLinkedList предоставляет независимые от времени методы вставки в середину списка, что может быть важно при работе со списками, содержащими тысячи элементов.
Если вы привыкли использовать QValueVector или QMap в Qt 3, то при переходе на Qt 4 подобные классы ( QVector, QMap) предоставят вам схожую функциональность.
[Предыдущая: Что нового в Qt 4 ] [ Начало ] [Следующая: Структура Interview ]
Copyright © 2007 Trolltech | Trademarks | Qt 4.3.2
|