Přetypování (C++/CX)
Čtyři různé operátory přetypování platí pro typy prostředí Windows Runtime: operátor static_cast, operátor dynamic_cast, operátor safe_cast a operátor reinterpret_cast. safe_cast a static_cast
vyvolá výjimku, pokud převod nelze provést; static_cast Operátor také provádí kontrolu typů kompilace. dynamic_cast
vrátí nullptr
, pokud se nepodaří převést typ. I když reinterpret_cast
vrátí hodnotu, která není null, může být neplatná. Z tohoto důvodu doporučujeme nepoužívat reinterpret_cast
, pokud nevíte, že přetypování bude úspěšné. Kromě toho doporučujeme, abyste v kódu C++/CX nepoužívali přetypování ve stylu jazyka C++/CX, protože jsou stejné jako reinterpret_cast
.
Kompilátor a modul runtime také provádějí implicitní přetypování , například v operacích boxování, když je typ hodnoty nebo předdefinovaný typ předán jako argumenty metodě, jejíž typ parametru je Object^
. Implicitní přetypování by v teorii nikdy nemělo způsobit výjimku za běhu; Pokud kompilátor nemůže provést implicitní převod, vyvolá chybu v době kompilace.
prostředí Windows Runtime je abstrakce modelu COM, která místo výjimek používá kódy chyb HRESULT. Obecně platí, že Platform::InvalidCastException označuje chybu modelu COM nízké úrovně E_NOINTERFACE.
static_cast
Zkontroluje se v době kompilace a static_cast
určí, jestli mezi těmito dvěma typy existuje vztah dědičnosti. Přetypování způsobí chybu kompilátoru, pokud typy nesouvisí.
A static_cast
třídy ref také způsobí provedení kontroly za běhu. Třída static_cast
ref může předat ověření doby kompilace, ale stále selže v době běhu; v tomto případě Platform::InvalidCastException
je vyvolán. Obecně platí, že tyto výjimky nemusíte zpracovávat, protože téměř vždy indikují programovací chyby, které můžete eliminovat během vývoje a testování.
Použijte static_cast
, pokud kód explicitně deklaruje relaci mezi těmito dvěma typy, a proto máte jistotu, že přetypování by mělo fungovat.
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
Operátor safe_cast je součástí prostředí Windows Runtime. Provede kontrolu typu za běhu a vyvolá Platform::InvalidCastException
chybu v případě selhání převodu. Použijte safe_cast , když selhání za běhu značí výjimečný stav. Hlavním účelem safe_cast je pomoct identifikovat chyby programování během fází vývoje a testování v okamžiku, kdy k nim dochází. Tuto výjimku nemusíte zpracovávat, protože neošetřená výjimka sama identifikuje bod selhání.
Použijte safe_cast, pokud kód nehlásí relaci, ale jste si jisti, že přetypování by mělo fungovat.
// 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
Použije dynamic_cast
se při přetypování objektu (konkrétně hat ^) na odvozenější typ, očekáváte, že cílový objekt může někdy být nullptr
nebo že přetypování může selhat, a chcete tuto podmínku zpracovat jako běžnou cestu kódu místo výjimky. Například v šabloně OnLaunched
projektu Prázdná aplikace (Univerzální windows) metoda v app.xaml.cpp používá dynamic_cast
k otestování, jestli okno aplikace obsahuje obsah. Není to chyba, pokud nemá obsah; jedná se o očekávanou podmínku. Windows::Current::Content
Windows::UI::XAML::UIElement
je a převod je na , Windows::UI.XAML::Controls::Frame
což je odvozenější typ v hierarchii dědičnosti.
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();
// ...
}
}
Dalším použitím dynamic_cast
je testovat, Object^
zda obsahuje typ krabicové hodnoty. V tomto případě se pokusíte o .dynamic_cast<Platform::Box>
dynamic_cast<Platform::IBox>
dynamic_cast a sledování odkazů (%)
Můžete také použít dynamic_cast
odkaz na sledování, ale v tomto případě se přetypování chová jako safe_cast. Platform::InvalidCastException
Vyvolá selhání, protože odkaz na sledování nemůže mít hodnotu nullptr
.
reinterpret_cast
Doporučujeme nepoužívat reinterpret_cast , protože se neprovádí kontrola doby kompilace ani kontrola za běhu. V nejhorším případě umožňuje, reinterpret_cast
aby se chyby programování nezjištěly v době vývoje a způsobovaly drobné nebo závažné chyby v chování programu. Proto doporučujeme použít reinterpret_cast
pouze v těch výjimečných případech, kdy je nutné přetypovat mezi nesouvisející typy a víte, že přetypování bude úspěšné. Příkladem vzácného použití je převod typu prostředí Windows Runtime na jeho základní typ ABI – to znamená, že přebíráte kontrolu nad počítání odkazů pro objekt. K tomu doporučujeme použít inteligentní ukazatel Třídy ComPtr. V opačném případě musíte konkrétně volat release v rozhraní. Následující příklad ukazuje, jak lze přetypovat ref třídy na .IInspectable*
#include <wrl.h>
using namespace Microsoft::WRL;
auto winRtObject = ref new SomeWinRTType();
ComPtr<IInspectable> inspectable = reinterpret_cast<IInspectable*>(winRtObject);
// ...
Pokud použijete reinterpret_cast
převod z jednoho prostředí Windows Runtime rozhraní na jiné, způsobíte, že objekt bude uvolněn dvakrát. Proto toto přetypování používejte pouze při převodu na rozhraní rozšíření komponent jiného typu než C++.
Typy ABI
Typy ABI jsou v hlavicích v sadě Windows SDK. Záhlaví jsou pohodlně pojmenována za obory názvů ,
windows.storage.h
například .Typy ABI žijí ve speciálním oboru názvů ABI ,
ABI::Windows::Storage::Streams::IBuffer*
například .Převody mezi typem rozhraní prostředí Windows Runtime a jeho ekvivalentním typem ABI jsou vždy bezpečné – to znamená
IBuffer^
naABI::IBuffer*
.Třída prostředí Windows Runtime by měla být vždy převedena na
IInspectable*
výchozí rozhraní, pokud je to známo.Po převodu na typy ABI vlastníte životnost typu a musíte postupovat podle pravidel modelu COM. Doporučujeme
WRL::ComPtr
zjednodušit správu životnosti ukazatelů ABI.
Následující tabulka shrnuje případy, ve kterých je bezpečné používat reinterpret_cast
. V každém případě je přetypování bezpečné v obou směrech.
Přetypování z, přetypování na | Přetypování na, přetypování z |
---|---|
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^* |