Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Cztery różne operatory rzutowania dotyczą typów środowiska uruchomieniowego systemu Windows: operator static_cast, operator dynamic_cast, operator safe_cast i operator reinterpret_cast.
safe_cast i static_cast zgłaszają wyjątek, gdy nie można wykonać konwersji; static_cast Operator wykonuje również sprawdzanie typów w czasie kompilacji.
dynamic_cast Metoda zwraca wartość nullptr , jeśli nie można przekonwertować typu. Chociaż reinterpret_cast zwraca wartość inną niż null, może być nieprawidłowa. Z tego powodu zalecamy, aby nie używać reinterpret_cast , chyba że wiadomo, że rzut zakończy się powodzeniem. Ponadto zalecamy, aby nie używać rzutów w stylu C w kodzie C++/CX, ponieważ są one identyczne z reinterpret_cast.
Kompilator i środowisko uruchomieniowe również wykonują niejawne rzutowania — na przykład w operacjach boksu, gdy typ wartości lub typ wbudowany są przekazywane jako argumenty do metody, której typem parametru jest Object^. Teoretycznie niejawne rzutowanie nigdy nie powinno powodować wyjątku w czasie wykonywania; Jeśli kompilator nie może wykonać niejawnej konwersji, zgłasza błąd w czasie kompilacji.
środowisko wykonawcze systemu Windows to abstrakcja modelu COM, która używa kodów błędów HRESULT zamiast wyjątków. Ogólnie rzecz biorąc, Platform::InvalidCastException wskazuje na błąd COM niskiego poziomu E_NOINTERFACE.
static_cast
Element static_cast jest sprawdzany w czasie kompilacji, aby określić, czy istnieje relacja dziedziczenia między dwoma typami. Rzutowanie powoduje błąd kompilatora, jeśli typy nie są powiązane.
Element static_cast w klasie ref powoduje również wykonanie sprawdzania czasu wykonywania. Klasa static_cast ref może przejść weryfikację czasu kompilacji, ale nadal kończy się niepowodzeniem w czasie wykonywania. W tym przypadku Platform::InvalidCastException zgłaszany jest błąd. Ogólnie rzecz biorąc, nie trzeba obsługiwać tych wyjątków, ponieważ prawie zawsze wskazują one błędy programistyczne, które można wyeliminować podczas programowania i testowania.
Użyj static_cast , jeśli kod jawnie deklaruje relację między dwoma typami, a zatem masz pewność, że rzutowanie powinno działać.
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
Operator safe_cast jest częścią środowiska uruchomieniowego systemu Windows. Wykonuje sprawdzanie typu czasu wykonywania i zgłasza Platform::InvalidCastException błąd, jeśli konwersja nie powiedzie się. Użyj safe_cast, gdy błąd czasu wykonywania wskazuje wyjątkowy warunek. Podstawowym celem safe_cast jest pomoc w identyfikowaniu błędów programowania w fazach programowania i testowania w momencie ich wystąpienia. Nie musisz obsługiwać wyjątku, ponieważ sam nieobsługiwany wyjątek identyfikuje punkt awarii.
Użyj safe_cast, jeśli kod nie deklaruje relacji, ale masz pewność, że rzutowanie powinno działać.
// 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
Należy użyć dynamic_cast podczas rzutowania obiektu (w szczególności kapelusza ^) do bardziej pochodnego typu, oczekuje się, że obiekt docelowy może czasami być nullptr lub że rzutowanie może zakończyć się niepowodzeniem i chcesz obsłużyć ten warunek jako zwykłą ścieżkę kodu zamiast wyjątku. Na przykład w szablonie projektu Pusta aplikacja (Universal Windows), metoda w app.xaml.cpp używa OnLaunched do testowania, czy okno aplikacji ma zawartość. Nie jest to błąd, jeśli nie ma zawartości; jest to oczekiwany warunek.
Windows::Current::Content jest elementem Windows::UI::XAML::UIElement , a konwersja jest na Windows::UI.XAML::Controls::Frame, który jest bardziej pochodnym typem w hierarchii dziedziczenia.
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();
// ...
}
}
Innym zastosowaniem dynamic_cast metody jest sondowania elementu w Object^ celu określenia, czy zawiera typ wartości pola. W takim przypadku próbujesz podjąć próbę lub dynamic_cast<Platform::Box> .dynamic_cast<Platform::IBox>
dynamic_cast i odwołania do śledzenia (%)
Można również zastosować element dynamic_cast do referencji śledzącej, ale w tym przypadku rzutowanie zachowuje się jak safe_cast. Zgłasza Platform::InvalidCastException błąd, ponieważ odwołanie do śledzenia nie może mieć wartości nullptr.
reinterpret_cast
Zalecamy, aby nie używać reinterpret_cast , ponieważ nie jest przeprowadzane ani sprawdzanie czasu kompilacji, ani sprawdzanie czasu wykonywania. W najgorszym przypadku możliwe jest, reinterpret_cast aby błędy programowania nie są wykrywane w czasie programowania i powodować subtelne lub katastrofalne błędy w zachowaniu programu. Dlatego zalecamy użycie reinterpret_cast tylko w tych rzadkich przypadkach, gdy należy rzutować między niepowiązanymi typami i wiedzieć, że rzutowanie zakończy się powodzeniem. Przykładem rzadkiego użycia jest przekonwertowanie typu środowisko wykonawcze systemu Windows na jego podstawowy typ ABI — oznacza to, że przejmujesz kontrolę nad liczeniem odwołań dla obiektu. W tym celu zalecamy użycie inteligentnego wskaźnika klasy ComPtr . W przeciwnym razie należy w szczególności wywołać metodę Release w interfejsie. W poniższym przykładzie pokazano, jak można rzutować klasę ref na klasę IInspectable*.
#include <wrl.h>
using namespace Microsoft::WRL;
auto winRtObject = ref new SomeWinRTType();
ComPtr<IInspectable> inspectable = reinterpret_cast<IInspectable*>(winRtObject);
// ...
Jeśli używasz reinterpret_cast metody do konwersji z jednego interfejsu środowisko wykonawcze systemu Windows na inny, obiekt zostanie zwolniony dwa razy. W związku z tym należy używać tego rzutowania tylko podczas konwertowania na interfejs rozszerzeń składników innych niż C++.
Typy ABI
Typy ABI działają w nagłówkach w zestawie Windows SDK. Wygodnie nagłówki są nazwane po przestrzeniach nazw — na przykład
windows.storage.h.Typy ABI działają w specjalnej przestrzeni nazw ABI — na przykład
ABI::Windows::Storage::Streams::IBuffer*.Konwersje między typem interfejsu środowisko wykonawcze systemu Windows a jego równoważnym typem ABI są zawsze bezpieczne — czyli
IBuffer^doABI::IBuffer*.Jeśli jest to znane, klasa środowisko wykonawcze systemu Windows powinna być zawsze konwertowana na
IInspectable*lub jej interfejs domyślny.Po przekonwertowaniu na typy ABI będziesz właścicielem okresu istnienia typu i musisz postępować zgodnie z regułami MODELU COM. Zalecamy, aby
WRL::ComPtruprościć zarządzanie okresem istnienia wskaźników ABI.
W poniższej tabeli przedstawiono podsumowanie przypadków, w których można bezpiecznie używać programu reinterpret_cast. W każdym przypadku obsada jest bezpieczna w obu kierunkach.
| Rzutowanie z, rzutowanie do | Rzutowanie do, rzutowanie 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^* |