Megosztás:


Öntvény (C++/CX)

Négy különböző öntött operátor vonatkozik a Windows futtatókörnyezeti típusokra: static_cast Operátor, dynamic_cast Operátor, safe_cast Operátor és reinterpret_cast Operátor. safe_cast és static_cast kivételt dob, ha az átalakítás nem hajtható végre; static_cast operátor fordítási idejű típusellenőrzést is végrehajt. dynamic_cast visszaadja nullptr , ha nem konvertálja a típust. Bár reinterpret_cast nem null értéket ad vissza, lehet, hogy érvénytelen. Ezért azt javasoljuk, hogy csak akkor használja reinterpret_cast , ha tudja, hogy a szereposztás sikeres lesz. Emellett azt is javasoljuk, hogy ne használjon C-stílusú öntötteket a C++/CX kódban, mert azok megegyeznek a C++/CX kóddal reinterpret_cast.

A fordító és a futtatókörnyezet implicit átalakítást is végrehajt – például a boxing műveletekben, amikor egy értéktípus vagy egy beépített típus argumentumként kerül átadásra egy olyan metódusnak, amelynek paramétertípusa Object^. Elméletben az implicit típuskonverziók soha nem okozhatnak kivételt futásidőben; ha a fordító nem tud implicit konverziót végrehajtani, a fordításkor hibát jelez.

A Windows Runtime a COM feletti absztrakció, amely kivétel helyett HRESULT hibakódokat használ. A Platform::InvalidCastException általában a E_NOINTERFACE alacsony szintű COM-hibáját jelzi.

static_cast (statikus kaszt)

A static_cast fordításkor a rendszer ellenőrzi, hogy van-e öröklési kapcsolat a két típus között. A leadott szöveg fordítási hibát okoz, ha a típusok nem kapcsolódnak.

Egy static_cast ref-osztályban egy futásidejű ellenőrzés is elvégzésre kerül. A static_cast egy ref-osztályon átmehet a fordítási idő ellenőrzésén, de futtatáskor mégis sikertelenül lefuthat; ebben az esetben egy Platform::InvalidCastException-t dob. Ezeket a kivételeket általában nem kell kezelnie, mert szinte mindig olyan programozási hibákat jeleznek, amelyeket a fejlesztés és tesztelés során kiküszöbölhet.

Akkor használja static_cast , ha a kód explicit módon deklarálja a két típus közötti kapcsolatot, ezért biztos benne, hogy a leadásnak működnie kell.

    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

A safe_cast operátor a Windows Futtatókörnyezet része. Futásidejű típusellenőrzést végez, és a konvertálás sikertelenségére ad parancsot Platform::InvalidCastException . Használjon safe_cast , ha egy futásidejű hiba kivételes feltételt jelez. A safe_cast elsődleges célja, hogy segítsen azonosítani a programozási hibákat a fejlesztési és tesztelési fázisokban az előfordulásuk helyén. Nem kell kezelnie a kivételt, mert maga a kezeletlen kivétel azonosítja a hibapontot.

Használja safe_cast, ha a kód nem deklarálja a kapcsolatot, de biztos benne, hogy a leadásnak működnie kell.

    // 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

Ha dynamic_cast egy objektumot (pontosabban egy kalapot ^) egy származtatottabb típusra vet, akkor azt várhatja, hogy a célobjektum néha hibás lehet nullptr , vagy a leadás meghiúsulhat, és ezt a feltételt normál kódútvonalként szeretné kezelni kivétel helyett. Az Üres alkalmazás (Univerzális Windows) projektsablonban például a OnLaunched app.xaml.cpp metódusa annak tesztelésére használja dynamic_cast , hogy az alkalmazásablak tartalmaz-e tartalmat. Ez nem hiba, ha nem rendelkezik tartalommal; ez egy várható feltétel. A(z) Windows::Current::Content egy Windows::UI::XAML::UIElement, és az átalakítás egy Windows::UI.XAML::Controls::Frame típusba történik, amely az öröklési hierarchiában egy származtatottabb típus.

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();
        // ...
    }
}

Egy másik felhasználási módja a dynamic_cast az, hogy megvizsgál egy Object^-t annak meghatározására, hogy tartalmaz-e dobozos értéktípust. Ebben az esetben egy dynamic_cast<Platform::Box> vagy egy dynamic_cast<Platform::IBox>.

dynamic_cast és nyomkövetési hivatkozások (%)

Alkalmazhatsz egy dynamic_cast egy követési referenciára, de ebben az esetben a leadás úgy viselkedik, mint a safe_cast. Hiba esetén Platform::InvalidCastException-t dob, mert a nyomkövetési hivatkozás értéke nem lehet nullptr.

reinterpret_cast

Javasoljuk, hogy ne használja a reinterpret_cast, mert sem fordítási időben, sem futásidőben nem történik ellenőrzés. A legrosszabb esetben lehetővé teszi, reinterpret_cast hogy a programozási hibák észrevétlenül menjenek a fejlesztési időben, és finom vagy katasztrofális hibákat okoznak a program viselkedésében. Ezért azt javasoljuk, hogy csak azokban a ritka esetekben használja reinterpret_cast, amikor nem kapcsolódó típusok között kell átalakítania, és tudja, hogy az átalakítás sikeres lesz. Ritka példaként említhetjük, amikor egy Windows Runtime típust alakít át a mögöttes ABI-típussá – ez azt jelenti, hogy az objektum referenciaszámlálását ön veszi át. Ehhez javasoljuk, hogy használja a ComPtr Osztály intelligens mutatót. Ellenkező esetben kifejezetten fel kell hívnia a Release-t a felületen. Az alábbi példa bemutatja, hogyan lehet egy ref osztályt átalakítani egy IInspectable* típusra.

#include <wrl.h>
using namespace Microsoft::WRL;
auto winRtObject = ref new SomeWinRTType();
ComPtr<IInspectable> inspectable = reinterpret_cast<IInspectable*>(winRtObject);
// ...

Ha reinterpret_cast használja arra, hogy egy Windows Runtime felületről egy másikra konvertáljon, azzal eléri, hogy az objektum kétszer legyen felszabadítva. Ezért csak akkor használja ezt a típuskonverziót, ha nem C++ összetevő kiterjesztés interfészére konvertál.

ABI-típusok

  • Az ABI-típusok fejlécekben találhatók a Windows SDK-ban. A fejlécek elnevezése kényelmes módon a névterekről, például windows.storage.h.

  • Az ABI-típusok egy speciális ABI névtérben élnek– például ABI::Windows::Storage::Streams::IBuffer*.

  • A Windows futtatókörnyezeti felület típusa és az azzal egyenértékű ABI-típus közötti konverziók mindig biztonságosak, IBuffer^ vagyis a következőre: ABI::IBuffer*.

  • Amennyiben ismert, a Windows futtatókörnyezeti osztályt mindig át kell alakítani IInspectable* vagy az alapértelmezett felületre.

  • Az ABI-típusokká alakítás után Ön a típus élettartamának tulajdonosa, és be kell tartania a COM-szabályokat. Javasoljuk, hogy a WRL::ComPtr segítségével egyszerűsítse az ABI-mutatók élettartam-kezelését.

Az alábbi táblázat azokat az eseteket foglalja össze, amelyekben biztonságosan használható reinterpret_cast. Minden esetben a művelet mindkét irányban biztonságos.

Típus átalakítás innen, típus átalakítás erre Öntés oda, öntés onnan
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^*

Lásd még