Namespaces

Variants
Actions

Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries over the next few weeks. Thanks for all your past and future contributions.

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

From 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 01:58.
229 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×