Bagikan melalui


Transmisi (C++/CX)

Empat operator transmisi yang berbeda berlaku untuk jenis Windows Runtime: Operator static_cast, Operator dynamic_cast, Operator safe_cast, dan Operator reinterpret_cast. safe_cast dan static_cast melemparkan pengecualian ketika konversi tidak dapat dilakukan; Operator static_cast juga melakukan pemeriksaan jenis waktu kompilasi. dynamic_cast mengembalikan nullptr jika gagal mengonversi jenis. Meskipun reinterpret_cast mengembalikan nilai non-null, nilai tersebut mungkin tidak valid. Untuk alasan ini, kami sarankan Anda tidak menggunakan reinterpret_cast kecuali Anda tahu bahwa pemeran akan berhasil. Selain itu, kami sarankan Anda tidak menggunakan cast gaya C dalam kode C++/CX Anda karena identik dengan reinterpret_cast.

Pengkompilasi dan runtime juga melakukan cast implisit—misalnya, dalam operasi tinju ketika jenis nilai atau jenis bawaan diteruskan sebagai argumen ke metode yang jenis parameternya adalah Object^. Secara teori, pemeran implisit tidak boleh menyebabkan pengecualian pada waktu proses; jika pengkompilasi tidak dapat melakukan konversi implisit, pengkompilasi akan menimbulkan kesalahan pada waktu kompilasi.

Windows Runtime adalah abstraksi melalui COM, yang menggunakan kode kesalahan HRESULT alih-alih pengecualian. Secara umum, Platform::InvalidCastException menunjukkan kesalahan COM tingkat rendah E_NOINTERFACE.

static_cast

static_cast diperiksa pada waktu kompilasi untuk menentukan apakah ada hubungan warisan antara kedua jenis tersebut. Pemeran menyebabkan kesalahan kompilator jika jenisnya tidak terkait.

static_cast Pada kelas ref juga menyebabkan pemeriksaan run-time dilakukan. static_cast Pada kelas ref dapat melewati verifikasi waktu kompilasi tetapi masih gagal pada waktu proses; dalam hal ini dilemparkanPlatform::InvalidCastException. Secara umum, Anda tidak perlu menangani pengecualian ini karena hampir selalu menunjukkan kesalahan pemrograman yang dapat Anda hilangkan selama pengembangan dan pengujian.

Gunakan static_cast jika kode secara eksplisit mendeklarasikan hubungan antara kedua jenis tersebut, dan oleh karena itu Anda yakin bahwa pemeran harus berfungsi.

    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 adalah bagian dari Windows Runtime. Ini melakukan pemeriksaan jenis run-time dan melempar Platform::InvalidCastException jika konversi gagal. Gunakan safe_cast saat kegagalan run-time menunjukkan kondisi yang luar biasa. Tujuan utama safe_cast adalah untuk membantu mengidentifikasi kesalahan pemrograman selama fase pengembangan dan pengujian pada titik di mana mereka terjadi. Anda tidak perlu menangani pengecualian karena pengecualian yang tidak tertangani itu sendiri mengidentifikasi titik kegagalan.

Gunakan safe_cast jika kode tidak mendeklarasikan hubungan tetapi Anda yakin bahwa pemeran harus berfungsi.

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

Gunakan dynamic_cast saat Anda mentransmisikan objek (lebih khusus, topi ^) ke jenis yang lebih turunan, Anda mengharapkan bahwa objek target kadang-kadang mungkin nullptr atau bahwa cast mungkin gagal, dan Anda ingin menangani kondisi tersebut sebagai jalur kode reguler alih-alih pengecualian. Misalnya, dalam templat proyek Aplikasi Kosong (Universal Windows),OnLaunched metode di app.xaml.cpp menggunakan dynamic_cast untuk menguji apakah jendela aplikasi memiliki konten. Ini bukan kesalahan jika tidak memiliki konten; ini adalah kondisi yang diharapkan. Windows::Current::ContentWindows::UI::XAML::UIElement adalah dan konversinya adalah ke Windows::UI.XAML::Controls::Frame, yang merupakan jenis yang lebih turunan dalam hierarki warisan.

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

Penggunaan lain adalah dynamic_cast menyelidiki Object^ untuk menentukan apakah berisi jenis nilai kotak. Dalam hal ini, Anda mencoba dynamic_cast<Platform::Box> atau dynamic_cast<Platform::IBox>.

dynamic_cast dan referensi pelacakan (%)

Anda juga dapat menerapkan dynamic_cast ke referensi pelacakan, tetapi dalam hal ini pemeran berperilaku seperti safe_cast. Ini melemparkan Platform::InvalidCastException kegagalan karena referensi pelacakan tidak dapat memiliki nilai nullptr.

reinterpret_cast

Kami menyarankan agar Anda tidak menggunakan reinterpret_cast karena pemeriksaan waktu kompilasi atau pemeriksaan run-time tidak dilakukan. Dalam kasus terburuk, reinterpret_cast memungkinkan kesalahan pemrograman tidak terdeteksi pada waktu pengembangan dan menyebabkan kesalahan halus atau bencana dalam perilaku program Anda. Oleh karena itu, kami sarankan Anda hanya menggunakan reinterpret_cast dalam kasus langka tersebut ketika Anda harus mentransmisikan antara jenis yang tidak terkait dan Anda tahu bahwa pemeran akan berhasil. Contoh penggunaan yang jarang dilakukan adalah mengonversi jenis Windows Runtime ke jenis ABI yang mendasarinya—ini berarti Anda mengontrol penghitungan referensi untuk objek tersebut. Untuk melakukan ini, kami sarankan Anda menggunakan penunjuk cerdas Kelas ComPtr. Jika tidak, Anda harus secara khusus memanggil Rilis pada antarmuka. Contoh berikut menunjukkan bagaimana kelas ref dapat dilemparkan ke IInspectable*.

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

Jika Anda menggunakan reinterpret_cast untuk mengonversi dari satu antarmuka Windows Runtime ke antarmuka lain, Anda menyebabkan objek dirilis dua kali. Oleh karena itu, hanya gunakan cast ini saat Anda mengonversi ke antarmuka ekstensi komponen non-C++.

Jenis ABI

  • Jenis ABI hidup di header di Windows SDK. Dengan nyaman, header dinamai sesuai dengan namespace—misalnya, windows.storage.h.

  • Jenis ABI hidup di namespace khusus ABI—misalnya, ABI::Windows::Storage::Streams::IBuffer*.

  • Konversi antara jenis antarmuka Windows Runtime dan jenis ABI yang setara selalu aman—yaitu, IBuffer^ ke ABI::IBuffer*.

  • Kelas Windows Runtime harus selalu dikonversi ke IInspectable* atau antarmuka defaultnya, jika diketahui.

  • Setelah Mengonversi ke jenis ABI, Anda memiliki masa pakai jenis tersebut dan harus mengikuti aturan COM. Kami menyarankan agar Anda menggunakan WRL::ComPtr untuk menyederhanakan manajemen seumur hidup pointer ABI.

Tabel berikut ini meringkas kasus di mana aman untuk menggunakan reinterpret_cast. Dalam setiap kasus, pemeran aman di kedua arah.

Cast dari, cast ke Cast ke, cast dari
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^*

Baca juga