Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Quatro operadores de transmissão diferentes se aplicam aos tipos do Tempo de Execução do Windows: Operador static_cast, Operador dynamic_cast, Operador safe_cast e Operador reinterpret_cast.
safe_cast e static_cast lançam uma exceção quando a conversão não puder ser executada; o operador static_cast também executa a verificação de tipo em tempo de compilação.
dynamic_cast retorna nullptr se não conseguir converter o tipo. Embora reinterpret_cast retorne um valor não nulo, ele pode ser inválido. Por esse motivo, recomendamos que você não use reinterpret_cast a menos que saiba que o elenco terá sucesso. Além disso, recomendamos que não utilize conversões de tipo estilo C no seu código C++/CX porque são idênticas a reinterpret_cast.
O compilador e o tempo de execução também realizam conversões implícitas — por exemplo, em operações de boxing quando um tipo de valor ou tipo embutido é passado como argumento para um método cujo tipo de parâmetro é Object^. Em teoria, um elenco implícito nunca deve causar uma exceção em tempo de execução; Se o compilador não pode executar uma conversão implícita, ele gera um erro em tempo de compilação.
O Tempo de Execução do Windows é uma abstração sobre COM, que usa códigos de erro HRESULT em vez de exceções. Em geral, o Platform::InvalidCastException indica um erro COM de baixo nível de E_NOINTERFACE.
static_cast
O static_cast é verificado durante a compilação para determinar se há uma relação de herança entre os dois tipos. O cast causa um erro de compilador se os tipos não estiverem relacionados.
A static_cast em uma classe ref também faz com que uma verificação de tempo de execução seja executada. Um static_cast numa classe de referência pode passar na verificação de tempo de compilação, mas ainda falhar em tempo de execução; neste caso, um Platform::InvalidCastException é lançado. Em geral, você não precisa lidar com essas exceções porque quase sempre elas indicam erros de programação que você pode eliminar durante o desenvolvimento e o teste.
Use static_cast se o código declarar explicitamente uma relação entre os dois tipos e, portanto, você tiver certeza de que o elenco deve funcionar.
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
O operador safe_cast faz parte do Tempo de Execução do Windows. Realiza uma verificação de tipo em tempo de execução e lança um Platform::InvalidCastException se a conversão falhar. Use safe_cast quando uma falha em tempo de execução indicar uma condição excecional. O principal objetivo do safe_cast é ajudar a identificar erros de programação durante as fases de desenvolvimento e teste no ponto em que ocorrem. Não é necessário manipular a exceção porque a própria exceção não tratada identifica o ponto de falha.
Use safe_cast se o código não declarar a relação, mas tiveres a certeza de que a conversão deve funcionar.
// 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
Use dynamic_cast quando você converte um objeto (mais especificamente, um chapéu ^) para um tipo mais derivado, você espera que o objeto de destino às vezes possa ser nullptr ou que a conversão possa falhar, e você deseja manipular essa condição como um caminho de código regular em vez de uma exceção. Por exemplo, no modelo de projeto Aplicativo em Branco (Universal Windows), o OnLaunched método em app.xaml.cpp usa dynamic_cast para testar se a janela do aplicativo tem conteúdo. Não é um erro se não tiver conteúdo; é uma condição esperada.
Windows::Current::Content é a Windows::UI::XAML::UIElement e a conversão é para um Windows::UI.XAML::Controls::Frame, que é um tipo mais derivado na hierarquia de herança.
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();
// ...
}
}
Outro uso de dynamic_cast é investigar um Object^ para determinar se contém um tipo de valor embutido. Nesse caso, tenta um dynamic_cast<Platform::Box> ou um dynamic_cast<Platform::IBox>.
dynamic_cast e referências de rastreamento (%)
Você também pode aplicar um dynamic_cast a uma referência de rastreamento, mas neste caso o elenco se comporta como safe_cast. Lança uma falha Platform::InvalidCastException porque uma referência de rastreamento não pode ter um valor de nullptr.
reinterpret_cast (operador de conversão de tipo em C++)
Recomendamos que você não use reinterpret_cast porque nem uma verificação em tempo de compilação nem uma verificação em tempo de execução são executadas. Na pior das hipóteses, a reinterpret_cast torna possível que erros de programação não sejam detetados no momento do desenvolvimento e causem erros sutis ou catastróficos no comportamento do seu programa. Portanto, recomendamos que você use reinterpret_cast apenas nos raros casos em que você deve lançar entre tipos não relacionados e você sabe que o elenco terá sucesso. Um exemplo de um uso raro é converter um tipo do Runtime do Windows no seu tipo ABI subjacente — isto significa que você está a tomar controlo da contagem de referências para o objeto. Para fazer isso, recomendamos que você use o ponteiro inteligente ComPtr Class . Caso contrário, você deve chamar especificamente Release na interface. O exemplo a seguir mostra como uma classe ref pode ser convertida para um IInspectable*.
#include <wrl.h>
using namespace Microsoft::WRL;
auto winRtObject = ref new SomeWinRTType();
ComPtr<IInspectable> inspectable = reinterpret_cast<IInspectable*>(winRtObject);
// ...
Se você usar reinterpret_cast para converter de uma interface do Tempo de Execução do Windows para outra, fará com que o objeto seja liberado duas vezes. Portanto, use este cast somente quando estiver a converter para uma interface de extensões de componentes que não são C++.
Tipos de ABI
Os tipos de ABI vivem em cabeçalhos no SDK do Windows. Convenientemente, os cabeçalhos são nomeados após os namespaces — por exemplo,
windows.storage.h.Os tipos ABI vivem num espaço de nomes especial ABI — por exemplo,
ABI::Windows::Storage::Streams::IBuffer*.As conversões entre um tipo de interface do Tempo de Execução do Windows e seu tipo ABI equivalente são sempre seguras, ou seja,
IBuffer^paraABI::IBuffer*.Uma classe do Tempo de Execução do Windows deve sempre ser convertida em
IInspectable*ou na sua interface padrão, caso essa seja conhecida.Depois de converter para tipos ABI, você possui o tempo de vida do tipo e deve seguir as regras COM. Recomendamos que você use
WRL::ComPtrpara simplificar o gerenciamento do tempo de vida dos ponteiros ABI.
A tabela a seguir resume os casos em que é seguro usar reinterpret_cast. Em todos os casos, o elenco está seguro em ambas as direções.
| Transmitir de, transmitir para | Conversão para, conversão de |
|---|---|
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^* |