Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Четыре разных оператора приведения применяются к типам среда выполнения 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^* |