Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
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::ComPtrsegí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^* |