Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Четыре разных оператора приведения применяются к типам среда выполнения Windows: оператор static_cast, оператор dynamic_cast, оператор safe_cast и оператор reinterpret_cast.
safe_cast и static_cast возникает исключение, если преобразование не может быть выполнено; оператор static_cast также выполняет проверку типа во время компиляции.
dynamic_cast возвращает значение nullptr , если не удается преобразовать тип. Хотя reinterpret_cast возвращает значение, отличное от NULL, оно может быть неверным. По этой причине рекомендуется не использовать reinterpret_cast , если нет уверенности, что приведение завершится успешно. Кроме того, рекомендуется не использовать приведения стилей C в коде C++/CX, так как они идентичны reinterpret_cast.
Компилятор и среда выполнения также выполняют неявное приведение, например в операциях упаковки, когда тип значения или встроенный тип передаются как аргументы в метод, параметры которого имеют тип Object^. Теоретически неявное приведение никогда не должно вызвать исключение во время выполнения; если компилятор не может выполнить неявное преобразование, он вызывает ошибку во время компиляции.
среда выполнения Windows — это абстракция по com, которая использует коды ошибок HRESULT вместо исключений. Как правило, Platform::InvalidCastException указывает на низкоуровневую ошибку E_NOINTERFACE модели COM.
static_cast
static_cast проверяется во время компиляции, чтобы определить, есть ли отношения наследования между двумя типами. Приведение вызывает ошибку компилятора, если типы не связаны.
Применение static_cast к классу ссылки также вызывает проверку времени выполнения. Применение static_cast к классам ссылок может пройти проверку при компиляции, но все равно приведет к сбою во время выполнения; в этом случае создается исключение Platform::InvalidCastException . В общем случае не следует обрабатывать эти исключения, поскольку они почти всегда указывают на ошибки программирования, которые можно устранить на этапах разработки и тестирования.
Используйте static_cast , если в коде явно объявлена связь между двумя, и поэтому вы уверены, что приведение должно работать.
interface class A{};
public ref class Class1 sealed : A { };
// ...
A^ obj = ref new Class1(); // Class1 is an A
// You know obj is a Class1. The compiler verifies that this is possible, and in C++/CX a run-time check is also performed.
Class1^ c = static_cast<Class1^>(obj);
safe_cast
Оператор safe_cast является частью среда выполнения Windows. Он выполняет проверку типов во время выполнения и создает исключение Platform::InvalidCastException при невозможности преобразования. Используйте safe_cast , если сбой во время выполнения указывает на исключительное условие. Основной целью safe_cast является выявление ошибок программирования во время этапов разработки и тестирования в точке их возникновения. Обрабатывать исключения не следует, поскольку необработанное исключение само определяет точку сбоя.
Используйте safe_cast, если в коде не объявлена связь, но вы уверены, что приведение должно работать.
// A and B are not related
interface class A{};
interface class B{};
public ref class Class1 sealed : A, B { };
// ...
A^ obj = ref new Class1();
// You know that obj's backing type implements A and B, but
// the compiler can't tell this by comparing A and B. The run-time type check succeeds.
B^ obj2 = safe_cast<B^>(obj);
dynamic_cast
Используйте dynamic_cast при приведение объекта (в частности, шляпу ^) к более производного типа, вы ожидаете, что целевой объект иногда может быть nullptr или что приведение может завершиться ошибкой, и вы хотите обработать это условие как обычный путь кода вместо исключения. Например, в шаблоне проекта пустого приложения (универсального приложения Windows) метод в app.xaml.cpp используется OnLaunched для проверки наличия содержимого окна приложения.dynamic_cast Это не ошибка, если она не имеет содержимого; это ожидаемое условие.
Windows::Current::Content является Windows::UI::XAML::UIElement , а преобразование выполняется в тип Windows::UI.XAML::Controls::Frame, который в иерархии наследования является более производным типом.
void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ args)
{
auto rootFrame = dynamic_cast<Frame^>(Window::Current->Content);
// Do not repeat app initialization when the window already has content,
// just ensure that the window is active
if (rootFrame == nullptr)
{
// Create a Frame to act as the navigation context and associate it with
// a SuspensionManager key
rootFrame = ref new Frame();
// ...
}
}
Другое использование оператора dynamic_cast — проверка объекта Object^ , чтобы определить, содержит ли он тип упакованного значения. В этом случае вы пытаетесь применить dynamic_cast<Platform::Box> или dynamic_cast<Platform::IBox>.
dynamic_cast и отслеживание ссылок (%)
Вы также можете применить dynamic_cast ссылку на отслеживание, но в этом случае приведение ведет себя так, как safe_cast. Оно создает исключение Platform::InvalidCastException при сбое, потому что отслеживаемая ссылка не может иметь значение nullptr.
reinterpret_cast (в C++, оператор для преобразования типов)
Не рекомендуется использовать reinterpret_cast , поскольку проверка не выполняется ни во время компиляции, ни во время выполнения. В худшем случае ошибки reinterpret_cast программирования могут быть незамечены во время разработки и вызывать тонкие или катастрофические ошибки в поведении вашей программы. Поэтому использовать reinterpret_cast рекомендуется только в тех редких случаях, когда необходимо выполнять приведение между несвязанными типами и известно, что такое приведение будет выполнено успешно. Примером редкого использования является преобразование типа среда выполнения Windows в базовый тип ABI. Это означает, что вы управляете подсчетом ссылок для объекта. Для этого рекомендуется использовать интеллектуальный указатель ComPtr Class . В противном случае необходимо явно вызывать Release для интерфейса. В следующем примере показано, как класс ссылки может быть приведен к IInspectable*.
#include <wrl.h>
using namespace Microsoft::WRL;
auto winRtObject = ref new SomeWinRTType();
ComPtr<IInspectable> inspectable = reinterpret_cast<IInspectable*>(winRtObject);
// ...
Если вы используете reinterpret_cast для преобразования из одного интерфейса среда выполнения Windows в другой, объект будет выпущен дважды. Поэтому используйте этот приведение только при преобразовании в интерфейс расширений компонентов, отличных от C++.
Типы ABI
Типы ABI расположены в заголовках в Windows SDK. Для удобства имена заголовков соответствуют именам пространств имен, например
windows.storage.h.Типы ABI расположены в специальном пространстве имен ABI, например
ABI::Windows::Storage::Streams::IBuffer*.Преобразования между типом интерфейса среда выполнения Windows и его эквивалентным типом ABI всегда безопасны , то есть
IBuffer^ABI::IBuffer*в .Класс среда выполнения Windows всегда должен быть преобразован в
IInspectable*или его интерфейс по умолчанию, если это известно.После преобразования к типам ABI вы управляете временем жизни типа и должны соблюдать правила модели COM. Рекомендуется использовать
WRL::ComPtr, чтобы упростить управление временем жизни указателей ABI.
В следующей таблице приведены случаи, в которых безопасно использовать reinterpret_cast. В каждом случае приведение безопасно в обоих направлениях.
| Приведение от, приведение к | Отлитый, отбрасываемый |
|---|---|
HSTRING |
String^ |
HSTRING* |
String^* |
IInspectable* |
Object^ |
IInspectable** |
Object^* |
IInspectable-derived-type* |
same-interface-from-winmd^ |
IInspectable-derived-type** |
same-interface-from-winmd^* |
IDefault-interface-of-RuntimeClass* |
same-RefClass-from-winmd^ |
IDefault-interface-of-RuntimeClass** |
same-RefClass-from-winmd^* |