×
Namespaces

Variants
Actions

Дескрипторы в качестве параметров функций

From Nokia Developer Wiki
Jump to: navigation, search
Article Metadata

Статья
Перевод:
Den123
Последнее редактирование: hamishwillee (09 Dec 2011)

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

void myFunction(TBuf<8> aText);

Недостаток такого решения заключается в том, что ограничен тип параметра - это TBuf (изменяемый стековый дескриптор), длиной 8 символов. Если в коде используется другой тип дескриптора, например RBuf, такую функцию нельзя будет вызвать напрямую.

Поэтому, если не требуется какой-то конкретной функциональности, в качестве параметров нужно использовать базовые типы дескрипторов: TDes (для изменяемых дескрипторов) и TDesC (для константных дескрипторов).

void SomeFunction(
const TDesC& aReadOnlyDescriptor,
TDes& aReadWriteDescriptor);

В приведенном выше примере, используется два типа дескрипторов:

  • Первый параметр - дескриптор только для чтения, константный дескриптор. TDesC - это базовый класс всех дескрипторов, в том числе и для изменяемого TDes. Даже если Вы используете RBuf, Вы можете передавать его в качестве параметра такого типа. Константный дескриптор плюс константная ссылка гарантируют, что содержимое дескриптора не будет изменено в ходе выполнения функции.
  • Второй параметр - дескриптор для чтения/записи. В отличие от первого, второй параметр не константный дескриптор TDes. Функция может изменять содержимое такого дескриптора, причем не имеет значения, где хранится его содержимое - в стеке или куче.


Другой важный момент - дескрипторы всегда нужно передавать по ссылке (например, TDesC&), а не по значению (например, TDes). При передаче по значению используется раннее связывание - в результате вызывающая функция получит объект базового типа, у которого не будет доступа к реальным данным. Компиляция такого кода пройдет без ошибок, однако во время выполнения возникнут проблемы. Воспользуйтесь отладчиком - Вы увидите, что вместо реальных данных такой параметр содержит мусор.


Пример API

Естественно, что в Symbian OS подобная парадигма используется для системных функций. Например, для чтения файла:

TInt errorCode = RFile.Read(TDes8& aDes);

У функции есть возможность узнать максимальный размер данных, которые может сохранить дескриптор с помощью метода aDes.MaxLength(), соответственно, ограничение максимального размера будет учтено при чтении файла. После вызова данной функции можно узнать, сколько байт было прочитано, используя вызов aDes.Length() - результат будет гарантировано меньше либо равен aDes.MaxLength().

Сравните с подобной функцией в Win32-API, где нет поддержки качественного строкового API. Для того, чтобы задать максимальный размер и вернуть количество прочитанных байт приходится использовать отдельные параметры:

BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, 
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
This page was last modified on 9 December 2011, at 04:58.
112 page views in the last 30 days.