Sdílet prostřednictvím


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::ContentWindows::UI::XAML::UIElement je a převod je na , Windows::UI.XAML::Controls::Framecož 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.hnapří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^ na ABI::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^*

Viz také