Page 1
WinRT berdiri diatas COM yang tetap memiliki mekanisme reference counting. Tetapi WinRT tidaklah
memiliki kerumitan yang dimiliki oleh COM sebelumnya. Hal ini dimungkinkan dengan c++/cx yang
merupkan penambahan fitur terhadap terhadap bahasa C++. Penambahan tersebut memberikan kita
kemudahan untuk mengkonsumsi dan membuat tipe WinRT kita sendiri.
C++/CX
Penambahan yang diberikan kepada c++/cx meliputi 3 area. Berikut table lengkap yang akan kita bahas
pada bagian berikutnya.
Untuk Allocation dibelakang layar COM menggunakan reference counting tetapi kita dengan
menggunakan c++/cx tidak perlu lagi terlibat langsung untuk hal ini. Kita tidak perlu melakukan release
atau delete secara manual. Secara otomatis dilakukan oleh runtime.
Kapan menggunakan c++/cx ?
Apakah kita harus menggunakan fitur c++/cx pada semua tempat ?
Jawabannya tentu saja tidak. Perhatikan gambar berikut
Page 2
Kita tidak perlu membuat semua kelas kita dengan c++/cx. Kita hanya perlu menggunakannya pada saat
kita akan berkomunikasi dengan WinRT. Untuk lingkungan internal maka kita dapat menggunakan ISO
C++. Jangan beranggapan bahwa kita akan meninggalkan ISO C++ sepenuhnya dan beralih ke CX. Hal ini
merupakan tanggapan yang salah. Anda tidak perlu merubah semua code base anda ke c++/cx agar
dapat digunakan pada metrostyle.
Dengan C++/CX kita tidak perlu lagi memanggil Windows API yang kita kenal dengan bahasa C dan COM
yang dulu. Tetapi dengan tipe WinRT yang memiliki konsep OOP, interface, event, delegate, class. Kita
dapat menikmati segala kemewahan yang kita miliki dari Object Oriented.
Anda juga dapat mengekspose library sehingga dapat dikonsumsi oleh bahasa lain dengan C++/CX. Kita
menamakannya WinRT component. Component ini dapat dikonsumsi oleh c#, vb, dan js.
Bahasa
Lifetime Management
Pada contoh program yang sebelumnya jika anda memperhatikan anda akan menemukan simbol yang
berbeda yaitu ^ (dibaca Hat).
Page 3
Handle ^ (hat) merupakan pointer ke WinRT dimana compiler secara otomatis melakukan reference
counting. Perhatikan deklarasi dari CameraCaptureUI.
Kedua deklarasi diatas sebenarnya sama. dengan keyword auto compiler akan menterjemahkan tipe
secara otomatis. Ini merupakan fitur dari c++11 yang membuat c++ menjadi modern. Anda dapat
melihat pada tutorial berikut.
Modern::C++ (Not Your GrandDaddy) C++
ref new digunakan untuk melakukan instansiasi dan mengaktifasi WinRT. dengan ref new maka yang
dikembalikan adalah ^ dan bukan *. Untuk melakukan de-reference masih tetap menggunakan dengan
cara yang sama menggunakan -> (arrow). Jadi tidak banyak berbeda sebenarnya dengan ISO c++.
Jika kita ingin membuat analogi maka kita bisa dapa menganggap bahwa ^ merupakan smart pointer.
Anda mungkin sudah biasa menggunakan CCOMPtr dari ATL library untuk mengatur AddRef dan Release
otomatis. Hanya saja sekarang kita tidak lagi menggunakannya secara langsung tetapi sudah di generate
oleh compiler. Optimasi juga dilakukan oleh kompiler sehingga performance nya sangat baik.
Runtime Class
Jika kita ingin membuat suatu component yang ingin diakses oleh bahasa lain, maka kita
mendefinisikannya dengan sebagai berikut.
Perhatikan bahwa untuk public method kita harus menggunakan tipe WinRT. Pada contoh diatas kita
memiliki Constructor person yang melewatkan parameter dengan tipe String^ yang merupakan tipe
WinRT.
Untuk method yang private/internal kita dapat menggunakan tipe c++ yang mana saja. Hal ini dapat
dilakukan karena akses private dan internal tidak dapat diakses dari luar assembly tersebut, sehingga
tidak ada kemungkinan untuk keluar dari ABI (Abstract Binary Interface). Pada contoh diatas kita melihat
method SetPassword dengan akses internal melewatkan parameter wstring.
Page 4
Sekarang saya akan melakukan demo untuk menjelaskan konsep yang telah kita pelajari sebelumnya
mengenai (^)hat, reference counting dan kelas.
Setup Project
Seperti biasa buat project c++ MetroStyle terlebih dahulu. Letakkan satu Button dan satu TextBox pada
Page tersebut. Perbesar ukuran dari TextBlock.
Berikan nama TextBlock tersebut karena kita akan melewatkannya sebagai parameter kelas. Hapus nilai
default valu dari TextBlock tersebut
Page 5
Perbesar ukuran dari text yang akan ditampilkan pada TextBlock, cara yang paling mudah untuk mencari
property ukuran font adalah dengan mengetikkan font pada search. Ubah ukurannya menjadi 16px
Double click button untuk membuat event handler pada button tersebut. Biarkan saja kosong untuk
sekarang.
Membuat Kelas
Buat kelas baru dengan mengklik kanan pada project anda dan memilih Add -> Class
Pilih add pada halaman berikutnya.
Page 6
Anda akan diarahkan untuk memberikan nama pada kelas tersebut dengan wizard. Beri nama Person
pada kelas tersebut maka Visual Studio akan mengenerate dua file yaitu header .h dan implementasi
.cpp
Page 7
KIta perhatikan bahwa pada solution explorer kita telah memiliki tambahan 2 file yaitu Person.h dan
Person.cpp
Pada header file Person ketikkan code berikut ini
Page 8
Kita membuat deklarasi kelas ref class dan sealed untuk WinRT type. Pada constructor kita melewatkan
object TextBlock. Perhatikan bahwa kita menggunakan Hat untuk merujuk kepada object tersebut. Kita
juga membuat private variable dengan tipe TextBlock untuk menyimpan reference terhadap txt. Kita
juga membuat satu public method untuk menampilkan pesan.
Sekarang kita akan mengimplementasikan Person pada Person.cpp
Kita akan membuktikan apakah benar memory tersebut akan di release dengan melakukan invoke
terhadap destructor secara otomatis. Anda juga sebenarnya dapat mengimplementasikan constructor
dan destructor secara inline pada header Person.h.
Kita sekarang akan menggunakan kelas tersebut pada kelas BlankPage.xaml.cpp. Jangan lupa untuk
menginclude Person.h.
Page 9
Sekarang kita akan mengisi implementasi dari event click handler pada button tersebut.
Kita melewatkan object TextBlock txtDisplay. Kita juga menggunakan ref new untuk instansiasi kelas dan
mereferencenya dengan Person^. Sekarang kita tinggal menjalankannya saja seperti biasa dengan F5.
Anda dapat melihat bahwa secara otomatis destructor akan dipanggil ketika object tersebut keluar dari
scope method button click. Dengan demikian kita tidak takut lagi dengan memory leak.
Interface
Kita juga mendapatkan tambahan fitur interface. Kita tahu bahwa konsep programming to interface
adalah salah satu practice yang dapat menuntun kita membuat aplikasi yang flexible dan mudah
menangani perubahan. Konsep ini juga digunakan untuk membuat design pattern.
Interface hanya berisi method saja dan tidak memiliki variable. secara default semua method yang di
deklarasikan di dalam interface adalah public. Berikut cara mendeklarasikannya.
Kita tidak perlu lagi menyebutkan virtual dan =0 untuk method tersebut. Karena semuanya sudah secara
implicit dilakukan oleh kompiler.
Interface juga dapat diturunkan dari interface yang lain.
Page 10
Semua method yang ada pada IAnimal akan diturunkan ke IFeline. Sekarang kita akan membuat kelas
Cat yang mengimplementasikan IFeline. Begini cara deklarasi dari header file Cat tersebut. Anda dapat
mengimplementasikannya sendiri.
Setelah anda membuat implemtasi dari kelas tersebut maka kita dapat menggunakannya dengan cara
merujuknya dari interfacenya dengan cara berikut.
Dengan interface kita dapat mengurangi coupling terhadap component lain.
Property
Mungkin beberapa diantara dari programmer c++ sudah familiar dengan konsep property dari c# atau
visual basic. Pada iso c++ kita tidak memiliki konsep property. Jika kita menerapkan konsep enkapsulasi
maka kita akan membuat data menjadi private dan membuat setter dan getter untuk mengakses data
tersebut. Property merupakan salah satu cara yang lebih baik untuk mengimplementasikan hal tersebut.
Dengan property kita seolah oleh memiliki data field tetapi kita tidak akses langsung. Hal ini membuat
kita dapat menyembunyikan detail implementasi dari kelas kita. Berikut ini adalah cara yang mudah
untuk membuat property.
Page 11
Pada contoh diatas kita membuat property Name yang secara otomatis compiler akan membuat data
member dengan akses private dan setter dan getter. Hal ini dibuat untuk mempermudah kita sehingga
kita tidak perlu repot mengimplementasikan hal yang trivial seperti berikut. Secara otomatis kompiler
akan membuatnya untuk kita.
Hal diatas baru bermanfaat jika kita ingin memiliki logic atau validasi yang ingin kita lakukan pada
property. Kita dapat mendefinisikan sebagai berikut.
Page 12
Pada property yang kita definisikan sendiri kita membuat setter (set())dan getter (get()). Pada contoh ini
kita juga membuat member data private. Kita bisa saja tidak membuatnya jika memang tidak
dibutuhkan. Anda juga tidak dapat hanya mengimplementasikan setter saja atau getter saja, tidak ada
kewajiban anda harus mengimplementasikan keduanya.
Cara menggunakannya adalah sama jika kita ingin memanggil member data field dari suatu kelas seperti
berikut.
Delegates
Kita dapat menganggap delegate adalah pointer ke function. Tetapi delegate adalah type safe dan dapat
dalam konteks ABI. Delegate merupakan tipe yang merujuk kepada operasi dan bukan kepada object.
Karena delegate adalah tipe maka kita dapat menginstansiasinya seperti yang kita lakukan terhadap
kelas. Hal ini berguna jika kita ingin mengimplementasikan event atau callback. Dengan demikian kita
dapat membuat program yang loose couple tidak terikat langsung kepada object tetapi hanya terhadap
Page 13
operasi tertentu. Berikut cara mendeklarasikannya, anda dapat melakukan deklarasi sama seperti
function.
Cara melakukan instansiasi terhadap delegate sama dengan yang kita lakukan dengan kelas. Kita
menggunakan ref new seperti berikut.
Pada contoh di atas kita membuat delegate yang merujuk fungsi yang kita definisikan dengan lambda.
Lambda merupakan fitur baru pada c++11. Anda dapat melihat daftar fitur baru yang ada pada c++11
pada tutorial saya sebelumnya.
Modern::C++ (Not Your GrandDaddy) C++
Selain dengan membuat dengan anonymous function atau lambda kita juga dapat melakukan
assignment terhadap delegate tersebut ke free function (fungsi yang tidak terikat kepada kelas tertentu)
atau ke method (fungsi yang terikat pada kelas tertentu).
Berikut contoh dengan menggunakan free function.
Jika anda memiliki fungsi dengan deklarasi sebagai berikut ini sebagai free function anda dapat meng-
assign langsung ke delegate.
Kita melakukan instansiasi delegate dengan cara sebagai berikut
Jika fungsi tersebut merupakan anggota dari kelas atau method, seperti berikut
Page 14
maka kita dapat melakukan instansiasi delegate dengan cara sebagai berikut.
Setelah anda selesai dengan melakukan inisialisasi terhadap delegate maka anda tinggal memanggilnya
sama seperti cara anda memanggil fungsi sebagai berikut.
Event
Anda bisa mengangap bahwa event adalah property dengan tipe delegate. Tetapi operasi yang kita
lakukan terhadap event bukan set dan get tetapi menambah(add), menghapus(remove) dan
mengeksekusi(raise) callback. Tipe yang digunakan untuk operasi terhadap event tersebut adalah tipe
delegate. Berikut cara deklarasi dari event tersebut.
Dengan cara diatas maka secara otomatis operasi add, remove dan raise akan dibuat oleh kompiler
untuk kita. Anda dapat membuat nya sendiri jika dibutuhkan.
Berikut cara yang kita lakukan untuk melakukan registrasi terhadap event tersebut. Kita menyebut
proses ini adalah subscribing.
Perhatikan bahwa kita selalu menambahkan instans dari delegate terhadap event. Pada contoh diatas
kita membuat object delegate dengan ref new yang merujuk pada method OnPropertyChangedHandler
pada kelas BlankPage.
Cara yang lain untuk melakukan subscribing adalah dengan cara sebagai berikut
Page 15
Dengan cara ini kita mendapatkan token dari hasil registrasi tersebut. Token inilah yang dapat kita
gunakan untuk melakukan unsubscribe (proses menghapus delegate yang sudah di register sebelumnya)
terhadap delegate tersebut. Caranya adalah sebagai berikut
Anda dapat memilih salah satu dari kedua cara diatas untuk melakukan unsubscribe.
Event merupakan fitur yang sangat mempermudah kita untuk melakukan observer pattern. Tetapi
jangan sampai salah menggunakannya karena juga akan dapat menyebabkan memory leak. Hal ini dapat
terjadi jika lupa melakukan unsubscribe terhadap object yang tidak anda rujuk lagi.
Exception
Pada dunia pemrograman dengan COM kita menggunakan HRESULT untuk melihat apakah terjadi
kegagalan operasi terhadap fungsi atau tidak. Hal ini menyebabkan code kita dapat terlihat seperti
berikut. Sehingga yang terjadi adalah pengecekan HRESULT untuk setiap operasi yang kita eksekusi.
Perhatikan code berikut
Dengan WinRT kita tidak lagi melakukan hal tersebut, karena kita sudah memiliki kelas dan semua fitur
dari object oritend lainnya, kita dapat membuat Exception. Dengan demikian kita dapat melakukan hal
diatas dengan lebih bersih. Jika terjadi kegagalan operasi maka kita akan melemparkan (throw)
Exception dan membiarkan bagian lain untuk menangkapnya (catch).
Page 16
Cara untuk melemparkan exception adalah dengan menggunakan keyword throw dan melewatkan
instans dari object yang dibuat dengan ref new.
Berikut ini adalah relasi antara HRESULT dan tipe Exception yang terdapat pada WinRT.
Jika ada HRESULT yang belum memiliki tipe exception dan anda ingin melemparkan HRESULT tersebut.
Mungkin anda ingin melakukannya untuk kompatibilitas dengan code COM yang telah anda buat
sebelumnya, anda dapat menggunakan COMException sebagai berikut.
Anda menangkap exception tersebut dengan menggunakan try catch sebagai berikut. Anda juga dapat
mengambil nilai HResult dari exception tersebut.
Page 17
Salah satu hal yang perlu diperhatikan pada penanganan exception ini adalah bahwa induk dari segala
exception yang ada pada WinRT adalah Platform::Exception. Sehingga jika anda ingin menangkap semua
tipe exception yang dilemparkan dari method yang dipanggil kita menggunakan cara berikut ini
Generic
Mungkin anda bertanya-tanya mengapa kita membutuhkan tipe generic lagi, bukankah kita sudah
memiliki template ? Apakah kita tidak lagi dapat menggunakan template ?
Hal yang pertama kali perlu kita ketahui adalah generic berbeda dengan template. Kita tetap saja dapat
menggunakan c++ template. Generic dibutuhkan pada WinRT untuk membuat tipe generic yang dapat
dikonsumsi oleh bahasa lain seperti c#, vb dan javascript. c++ template tidak akan dikenali jika keluar
dari ABI.
Saya sudah membahas mengenai pentingnya programming to interface. Kita mungkin saja ingin
membuat API yang dapat diakses oleh bahasa lain dengan mengembalikan interface yang generic
sehingga kode client yang menggunakan API tersebut tidak terikat pada detail dari implementasinya.
Berikut contoh dari generic interface
Kita membuat kelas konkret yang mengimplementasikan interface generic tersebut sebagai berikut
Page 18
Jika anda melihat tanda garis bawah merah pada kode anda (yang biasanya ditujukan untuk
menandakan bahwa ada error ) maka anda dapat melakukan build untuk memastikan bahwa semua bisa
di kompilasi. Kadang kadang error yang ditunjukkan tidak benar sehingga pastikan selalu dengan
melakukan kompilasi. Untuk versi beta ini masih banyak kesalahan untuk hal tersebut, sehingga anda
harap maklum.
Generic interface ini dimengerti oleh WinRT metadata. Sehingga dapat digunakan dari bahasa lain. Kita
tentu saja memerlukan kelas yang mengimplementasikan interrface tersebut. berikut cara untuk
melakukannya.
Dengan adanya interface kita dapat menyembunyikan detail implemntasi dari kelas konkrit yang kita
miliki. Aplikasi kita menjadi loose couple sehingga jika dikemudian hari terjadi perubahan maka kita
dapat menggati kelas tersebut dengan kelas lain tanpa mempengaruhi kode program yang
menggunakan interface tersebut.
Template Runtime Class
Generic dapat dimengerti oleh bahasa lain dan metadata, tetapi kita tetap saja membutuhkan template.
Karena template memiliki fitur yang tidak dimiliki oleh generic. Kelebihan dari template terletak pada
fleksibilitas, spesialisasi, compile time, kompresi. Hanya saja template tidak dikenali di luar c++ oleh
bahasa lain. Tetapi kita tetap dapat menggunakannya dengan generic untuk memperoleh kombinasi
yang sangat baik. Kita dapat memiliki template untuk class dengan sebagai berikut.
sehingga kita dapat mengubah implementasi yang sebelumnya menjadi seperti berikut ini
Page 19
Kita menyembunyikan implemntasi dari template tersebut dari luar kode c++, sehingga c#, vb dan
javascript tidak perlu mengetahui mengenai template tersebut.
Partial Runtime class
Dengan kelas parsial kita dapat memisahkan implementasi dari satu kelas ke beberapa file. Hal ini
ditujukan untuk memisahkan code yang digenerate oleh tools dengan code yang kita tulis sendiri.
Karena jika kita mengenerate ulang dengan bantuan tools dan kita melakukan perubahan pada file hasil
generate tersebut, perubahan kita akan dihapus.
Visual studio sangat bergantung pada fitur ini untuk membuat XAML dan code behind bekerja dengan
baik utk c++. Anda dapat melihatnya sendiri pada solution. Caranya adalah aktifkan Show All Files
sehingga anda dapat melihat semua code yang digenerate.
Anda akan melihat beberapa file yang digenerate memiliki nama yang sama dengan kelas dimana kita
sebelumhya bekerja. BlankPage.h memiliki pasangan BlankPage.g.h. Jika anda melihat isi dari
BlankPage.g.h anda dapat melihat bahwa kelas tersebut merupakan partial class.
Page 20
Pasangannya adalah BlankPage.h yang telah kita sering gunakan sebelumnya.
Pada saat compile time maka kedua kelas tersebut akan digabungkan menjadi satu seolah-olah semua
isi kode yang ada di kelas partial BlankPage.g.h tersebut ada di kelas BlankPage.h.
Library
WinRT memiliki kelas Collection sendiri, hal ini tentu saja ditunjukan untuk kepentingan ABI (Abstract
Binary Interface). Kita tetap saja dapat menggunakan collection dari STL yang sudah sering kita gunakan
dan kedua tipe tersebut dapat saling bekerja sama dengan mudah.
Vector
Pada WinRT collection kita memiliki Vector dan ObserverableVector. Anda tentu sudah mengetahui
bahwa pada STL kita memiliki std::vector. Vector terletak pada namespace Platform::Collection. Kita
dapat menggunakannya dengan cara berikut. Pertama jangan lupa untuk using namespace tersebut
Kemudian kita dapat melakukan instansiasi sama seperti tipe WinRT yang lain menggunakan ref new.
Page 21
Jika anda ingin melakukan iterasi terhadap Vector tersebut anda dapat menggunakan IVectorView yang
dilakukan dengan cara berikut.
IVectorView merupakan iterator yang hanya dapat dibaca saja isinya tanpa merubah (read only).
Tujuannya digunakan untuk melakukan navigasi terhadap elemen dari vector tersebut.
Vector juga memiliki mekanisme untuk memberitahukan apabila terjadi perubahan pada vector
tersebut, penambahan elemen dsb. Hal itu dilakukan dengan menggunakan event dan delegate sebagai
berikut.
Map
Untuk tipe dictionary dengan key dan value, kita memiliki Map yang memiliki padanan dengan std::map
pada c++ standard. Sama dengan Vector terletak pada Platform::Collection. Berikut sekilas cara
penggunaanya.
Page 22
Kita dapat menggunakan kelas kelas collection WinRT yang dijelaskan pada bagian sebelum dengan STL.
Kita sudah tahu bahwa agar algoritma yang ada pada STL dapat bekerja kita harus memiliki method
begin() dan end() pada kelas yang akan kita iterasi. Kelas String dan Collection yang ada pada WinRT
telah mengimplementasikan kedua method tersebut sehingga dapat bekerja dengan baik dengn
algoritma STL. Berikut kita lihat cara penggunaanya.
Jika anda lakukan analisa terhadap kode tersebut maka kita tidak melihat banyak perbedaan dengan apa
yang kita lakukan pada kode c++ standard sebelumnya. begin() dan end() sudah di implementasikan oleh
setiap WinRT collection pada collection.h. Anda dapat membuktikannya dengn membuka file
collection.h. Anda dapat menemukannya pada solution explorer pada bagian external dependency.
Atau anda dapat langsung melakukan navigasi dengan memanfaatkan bantuan search visual studio
dengan cara klik kanan pada code begin() atau end() dan pilih go to definition (F12).
Page 23
Anda dapat memperhatikan definisi tersebut seperti berikut.
seperti yang sudah kita pelajari pada bagian sebelumnya kita dapat menggunakan tipe c++ standard di
dalam boundary (ABI), tetapi jika kita telah melewati batas tersebut kita harus menggunakan tipe
WinRT. Oleh karena itu kita membutuhkan cara untuk konversi dari WinRT ke c++ standard dan
sebaliknya. Fungsi konversi tersebut sudah disediakan dan tinggal kita gunakan saja.
Dari Platform::String ke std::wstring kita menggunakan cara sebagai berikut
Page 24
Dari std::wstring ke Platform::String kita menggunakan Constructor String seperti berikut ini.
Dari std::vector ke Platform::Collections::Vector kita melakukan dengan bantuan Constructor seperti
yang kita lakukan pada String sebelumnya seperti berikut
Untuk mengubah Platform::Collections::Vector menjadi std::vector maka kita menggunakan fungsi yang
ada pada collection.h yaitu to_vector() seperti berikut ini
Anda dapat melihat definisi dari to_vector dengan menekan F12 pada fungsi tersebut. definisi tersebut
terletak di collection.h