Применение этого ключевого слова не ограничено визуальным программированием, однако также участвует в поддержке кода VCL.
Общее применение _declspec
Выражение вида _declspec (аргумент) является модификатором, который может применяться к функциям или переменным. Аргументы dllexport, dilimport и thread формируют модификаторы, соответствующие обычным export, _import и _thread. Разница между ними заключается в том, что обычные модификаторы должны всегда непосредственно предшествовать имени объявляемой переменной или функции, в то время как модификаторы _declspec можно помещать в любом месте объявления:
void _declspec(dllexport) f(void);// Верно.
_declspec(dllexport) void f(void);// Верно.
_export void f(void) // Ошибка: должно быть
// void export.
Другими аргументами _declspec общего применения являются:
naked: Применяется к определению функции. Подавляет генерацию кода пролога/эпилога вызова, позволяя программисту написать свой собственный код, используя встроенный ассемблер.
noreturn: Сообщает компилятору, что функция не возвращает управления вызывающей программе. Обычно, когда компилятор обнаруживает, что при некоторых условиях функция, объявленная с типом возвращаемого значения, ничего не возвращает, он выдает предупреждение. Однако если эта ситуация связана с вызовом другой функции, не возвращающей управления, то, объявив последнюю с модификатором _declspec (noreturn), можно подавить такое предупреждение. Вот пример:
_declspec(noreturn) void finish(){
...
throw "No return";
}
int RetInt(){
if(....)
return 1;
else
finish(); // Без noreturn генерировалось бы
// предупреждение.
nothrew: Соответствует спецификации исключения без аргументов. Следующие объявления эквивалентны:
__declspec(nothrow) void f();
voidf() throw();
novtable: Применяется к классам, для которых никогда не будет создаваться представителей. В большинстве случаев этот модификатор подавляет генерирование vtaDie и, соответственно, кода всех функции,на которые она ссылается.
property: Позволяет реализовать в классе не статические “виртуальные элементы данных”, нечто вроде свойств. Синтаксис:
_declspec(property(get = get-функция,
put = put-функция)) объявление_ элемента;
Одна из спецификаций функций доступа может быть опущена. Компилятор транслирует обращения к “элементу данных” в вызовы функций доступа. Возможно также объявление “массива” с одним или несколькими “индексами”:
declspec(property(get=GetVal, put=PutVal)) int vArr[];
Число индексов в обращении к виртуальному массиву должно соответствовать числу параметров у функций доступа. (У простой виртуальной переменной get-функция не имеет ни одного, а put-функция имеет один параметр — присваиваемое значение.) Индексы не обязательно должны быть целыми, они могут быть, например, строками.
selectany: Применяется к глобальным переменным. В ANSI C/C++ принята концепция пробного определения (tentative definition). Если встречается объявление глобальной переменной без модификаторов класса хранения и без инициализации, оно рассматривается как пробное определение. Если тот же идентификатор появляется позднее в другом файле, предыдущее пробное определение считается объявлением external.
Однако инициализация глобальной переменной должна производиться только в одном месте. Если, например, глобальная переменная объявляется и инициализируется в заголовочном файле, подключаемом несколькими файлами проекта, при компоновке возникнет ошибка. Спецификация seiectany решает эту проблему:
_declspec(selectany) int gint = 10;
// Может появляться в
// нескольких файлах проекта.
selectany не может применяться к неинициализируемым переменным и переменным, недоступным за пределами текущего файла (т. е. глобальным статическим, например, глобальным константам C++ без спецификатора external).
uuid: Присоединяет GUID к объявляемому классу. Применяется только к СОМ-классам. Синтаксис:
_Declspec (uuid("GUID_COM-объекта") )
объявление/определение класса
Применение _declspec с VCL
Перечисленные ниже аргументы _declspec, служащие для поддержки VCL, редко применяются непосредственно. Они используются в макросах, определяемых файлом vcl\sysmac.h.
delphiclass: Может применяться для объявления классов, производных от TObject. Для классов, объявленных с этим аргументом _declspec, обеспечивается совместимость с VCL no RTTI, поведению конструкторов/деструкторов и обработке исключений. Накладываются также некоторые ограничения: класс не может быть сложным производным, его представители могут создаваться только динамически, он обязан иметь деструктор и для него не генерируются автоматически конструктор копии и операция присваивания по умолчанию.
delphireturn: Только для внутреннего использования VCL в C++Builder. Служит для поддержки встроенных типов ObjectPascal, для которых не существует эквивалентов в C++. Применяется в реализациях классов C++Builder Currency, AnsiString, Variant, TDateTime и Set.
dynamic: Служит для объявления динамических функций. По своему поведению они не отличаются от виртуальных, но реализуются по-другому. Они включаются в виртуальную таблицу только того класса, который их определяет. Тем самым экономится память, но падает эффективность, так как иногда приходится производить поиск в виртуальных таблицах, возможно, нескольких базовых классов. Аргумент может применяться только к функциям классов, производных от TObject.
hidesbase: В языке Object Pascal виртуальные функции базового класса могут появляться в производном как функции, не имеющие никакого отношения к одноименным функциям базового класса (это имеет место, если у производной функции не указан спецификатор override). Применение hidesbase к объявлению функции производного класса моделирует эту семантику Object Pascal.
package: Показывает, что код класса может компилироваться в пакете. При создании пакетов спецификатор генерируется компилятором автоматически.
pascalimplementation: Показывает, что код класса реализован на Object Pascal. Применяется в заголовочных файлах .hpp, моделирующих интерфейс Pascal-классов VCL.