Haftalık C++ 32 – Kullanıcı Tanımlı Dönüştürme Fonksiyonları (“User-defined Conversion Functions)

C++ 11 ile ilgili gelen özelliklere göz atmaya, son hızla devam ediyoruz.

Yine Modern C++ (2): C++ 11 Yenilikleri‘de eksik kalan konulardan birisi, benim de açıkçası daha önce pek aşina olmadığım bir kabiliyet olan “kullanıcı tanımlı dönüştürme fonksiyonlarına” hızlıca bakacağız. Bazı kaynaklarda, dönüştürme işlevleri, diye de geçebiliyor. Konu başlık itibari ile aslında, tür dönüşümü gibi çok önemli ve geniş bir konu başlığının içerisinde yer alıyor. Biz burada, özellikle bu kabiliyete bakacağız ama öncesinde çok kısaca C++’da hangi durumlarda dönüştürme yapıldığına bir göz atalım. C++ ile gelen standart dönüşüm işlevleri, temel tipler ile kullanıcı tanımlı tipler arasında ya da standart tipler arasında olabilmektedir. Bu tarz dönüşümlere aşağıdaki örnekleri verebiliriz:

  • Tam sayılar arası dönüşümler (enumerasyonlardan tam sayılara veya tam tersi, char/short/int/long/long long dönüşümleri). Burada küçük boyutlu veri tipinden büyük olana dönüşüm ya da tersini kapsamaktadır,
  • İşaretli ve işaretsiz sayılar arası dönüşümler (signed/unsigned),
  • Kayan noktalı sayılar arası dönüşümler (float/double) ile kayan sayı/tam sayı dönüşmleri,
  • Ve son olarak aritmetik operasyonlar sırasında gerçekleştirilen dönüşüm işlemleri.

Bu basit dönüşümlerin yanında aşağıdaki dönüşüm işlevleri de sunulmaktadır:

  • İşaretçi dönüşümleri (void*’dan diğer tiplere ya da tam tersi)
  • İşaretçi sınıflar arası dönüşüm (temel sınıftan türeyen sınıfa ya da tam tersi),
  • Fonksiyon işaretçi ve sınıf üye fonksiyon işaretçi dönüşümleri,
  • Referanstan işaretçiye dönüşümler.

Yukarıdaki dönüşümler belirgin ve açık bir şekilde (explicit) yapılabildiği gibi, üstü kapalı bir şekilde de (implicit) yapılabilmektedir. Her ne kadar C++, bir çok dönüşümü sizin yerinize bu şekilde yapsa da, bir çok kodlama standardı ve özellikle emniyet kritik yazılımlarda bu tarz üstü kapalı dönüşümlerden kaçınılmaktadır. Keza daha önce sizler ile paylaştığım yazılım hatalarına ilişkin kazaların bir kısmı ne yazık ki bu tarz dönüşüm hatalarından kaynaklanmış 🙁

Genelde bir çok derleyici bu tarz dönüşümlerde, derleme zamanında uyarı vererek sizleri bilgilendiriyor. Ayrıca C++ ile gelen explicit anahtar kelimesi ile tanımlanmış olan yapıcı (constructor)’lar da bu tarz hataların (üstü kapalı dönüşümler ile oluşabilecek) önüne geçmek amacı ile sunulmaktadır. Benzer şekilde daha önce haftalık C++ yazılarımın birisinde (Haftalık C++ 27 – Dönüştürücü Yapıcılar) C++ 11 ile gelen bir diğer yapıcı mekanizmalara değinmiştik. Bu mekanizmaların hepsi bir şekilde yanlışlıkla yapılan bu tarz hataları derleyici hatası olarak kullanıcıya sunup, bunları belirgin hale getirmek.

Bunların yanında elbette static_cast, dynamic_cast, reinterpret_cast ve const_cast araçlarını da kullanabilirsiniz.

Evet sözü daha fazla uzatmadan kullanıcı-tanım dönüşüm tanımlamasına gelelim. Aslına bakarsanız bu kabiliyet daha C++ 11’den önce de sunulmuştu ve aşağıdaki gibi tanımlanabilmekteydi:

Bu yetenek sayesinde, ilgili tip dönüşümleri hem açık hem de üstü kapalı bir şekilde yapılabilmekteydi. Fakat burada, halen açıkta kalan bir husus var, diyelim ki yukarıda “double o” tipine bir üstü kapalı dönüşümün yapılmasını istemiyorsunuz ne yapacaksınız?

İşte C++ 11 ile gelen yenilik bu sıkıntıya derman oluyor. Dönüşüm fonksiyonunun başına (operator int() const) “explicit” eklediğiniz zaman, artık “double o = instance;” ‘a derleme hatası alıyor olacağız. Peki  sadece o satıra mı? Hayır, “int m = instance;” satırına da artık hata alıyor olacağız, çünkü her türlü üstü kapalı int dönüşümlerini engellemiş oluyoruz.

Kaynaklar:

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

This site uses Akismet to reduce spam. Learn how your comment data is processed.