Tip Dönüşümü

Sayısal tipleri dönüştürmek

Sıklıkla, bir sayısal tipi diğerine dönüştürme ihtiyacı doğar. Tüm sayısal tipler birbirlerine dönüştürülemezler. İzin verilen dönüşümlerin şeması:

Muhtemel tip dönüşümü şeması

Oklu kalın çizgiler neredeyse hiç bilgi kaybı olmadan gerçekleştirilen değişimleri gösterir. Char tipinin yerine bool tipi kullanılabilir (ikisi de 1 bayt bellek kaplar), int tipinin yerine color tipi kullanılabilir (4 bayt), long tipinin yerine datetime kullanılabilir (8 bayt kaplarlar). Aralıklı çizgi oklar çözünürlük kaybı gerçekleşebilecek dönüşümleri gösterir. Örneğin bir tamsayıdaki (int) hanelerin sayısı 123456789'a eşittir . Bu, float tipiyle temsil edilebilecek hane sayısından büyüktür.

   int n=123456789;
   float f=n;    // içerik, 1.234567892E8'e eşittir
   Print("n = ",n,"   f = ",f);
   // sonuç n= 123456789    f= 123456792.00000

float tipine dönüştürülen bir sayı aynı düzende olur ama daha az doğrudur. Siyah okların ters yönünde yapılan dönüşümler, muhtemel veri kaybı ile gerçekleştirilebilir. char ve uchar, short ve ushort, int ve uint, long ve ulong dönüşümleri (iki yöne dönüşümler) veri kaybına yol açabilir.

Kayan nokta değerlerinin tamsayı tipine dönüşümünün bir sonucu olarak, ondalık kısım daima silinir. Eğer float tipli bir sayıyı en yakın tamsayıya yuvarlamak istiyorsanız (-ki bir çok durumda daha kullanışlıdır), MathRound() fonksiyonunu kullanmalısınız.

Örnek:

//--- Kütleçekim ivmesi
   double g=9.8;
   double round_g=(int)g;
   double math_round_g=MathRound(g);
   Print("round_g = ",round_g);
   Print("math_round_g = ",math_round_g);
/*
  Sonuç:
   round_g = 9
   math_round_g = 10
*/

Eğer iki değer, bir ikili işlem ile birleştirilmişse; işlem gerçekleştirilmeden önce daha düşük tipli işlenen, altta yer alan şemadaki önceliğe göre daha yüksek olan tipe dönüştürülür:

İkili işlemle bağlanma durumunda dönüşüm

Veri tipleri char, uchar, short ve ushort; istisnasız olarak int tipine dönüştürülürler.

Örnekler:

   char   c1=3;
//--- İlk örnek
   double d2=c1/2+0.3;
   Print("c1/2 + 0.3 = ",d2);
// Sonuç:   c1/2+0.3 = 1.3
 
//--- İkinci örnek
   d2=c1/2.0+0.3;
   Print("c1/2.0 + 0.3 = ",d2);
// Sonuç:   c1/2.0+0.3 = 1.8

Hesaplanan ifade iki işlemden oluşuyor. İlk örnekte, char tipli c1 değişkeni int tipi bir geçici değişkene dönüştürülür. Çünkü bölümdeki ikinci işlenen, sabit 2'nin tipi daha yüksektir. 3/2 tamsayı bölümünün sonucunda int tipli '1' değerini elde ederiz.

Birinci örneğin ikinci işleminde, ikinci işlenen double tipli '0.3' sabitidir. Bu yüzden, ilk işlemin sonucu 1.0 değeri ile double tipli geçici değişkene dönüştürülmüştür.

İkinci örnekte char tipli değişken c1, double tipli bir geçici değişkene dönüştürülmüştür, çünkü bölme işleminin ikinci işleneni sabit '2.0', double tiplidir. Başka dönüşüm yapılmamıştır.

 

Sayısal Tiplerin Dönüşümü

MQL5 dilindeki ifadelerde, açık ve gizli (kapalı) olmak üzere iki tip dönüşümü de kullanılabilir. Açık tip dönüşümü şu şekilde yazılır:

var_1 = (tip)var_2;

Bir ifade veya fonksiyon sonucu, var_2 değişkeni olarak kullanılabilir. Açık tip dönüşümünün fonksiyonel ifadesi de mümkündür:

var_1 = tip(var_2);

Birinci örnek temelinde bir açık tip dönüşümü düşünelim.

//--- Üçüncü örnek
   double d2=(double)c1/2+0.3;
   Print("(double)c1/2 + 0.3 = ",d2);
// Sonuç:   (double)c1/2+0.3 = 1.80000000

Bölme işlemi gerçekleştikten sonra c1 değişkeni açık olarak double tipine dönüştürülür. Ardından tamsayı sabiti 2, double tipli 2.0 değişkenine dönüşür. Dönüşümün sonucu olarak ilk işlenen, double tipini alır. Açık tip dönüşümü tekil bir işlemdir.

Ayrıca, tipleri dönüştürürken sonuç hoş görülebilir sınırların dışına çıkabilir. Bu durumda budama gerçekleşir. Örneğin:

   char c;
   uchar u;
   c=400;
   u=400;
   Print("c = ",c); // Sonuç c=-112
   Print("u = ",u); // Sonuç u=144

İşlemler gerçekleştirilmeden önce (atama işlemleri hariç); veri, en yüksek öncelikli tipe dönüştürülür. Atama işlemlerinden önce ise veri, hedef tipe dönüştürülür.

Örnekler:

   int    i=1/2;        // tip dönüşümü yok, sonuç 0
   Print("i = 1/2  ",i);
 
   int k=1/2.0;         // ifade double tipine dönüştürüldü,
   Print("k = 1/2  ",k);  // sonra int hedef tipine dönüştürüldü, sonuç 0
 
   double d=1.0/2.0;    // tip dönüşümü yok, sonuç 0.5
   Print("d = 1/2.0; ",d);
 
   double e=1/2.0;      // ifade double tipine dönüştürüldü,
   Print("e = 1/2.0; ",e);// hedef tipi ile aynı, sonuç 0.5
 
   double x=1/2;        // ifade double hedef tipine dönüştürüldü,
   Print("x = 1/2; ",x);  // sonuç 0.0

long/ulong tipli değişkenler double tipine dönüştürüldüğünde, tamsayı değerinin 9223372036854774784'den büyük veya -9223372036854774784'den küçük olması durumunda çözünürlük kaybı olabilir.

void OnStart()
  {
   long l_max=LONG_MAX;
   long l_min=LONG_MIN+1;
//--- double tipine dönüştürürken çözünürlük kaybı olmayacak en yüksek tamsayı değerini tanımla
   while(l_max!=long((double)l_max))
      l_max--;
//--- double tipine dönüştürürken çözünürlük kaybı olmayacak en düşük tamsayı değerini tanımla
   while(l_min!=long((double)l_min))
      l_min++;
//--- elde edilen aralığı tamsayı değerlerle yaz  
   PrintFormat("Bir tamsayı değerini double tipine dönüştürürken, "
               "değer, [%I64d, %I64d] aralığının içinde olmalı",l_min,l_max);
//--- şimdi, değer bu aralığın dışına düştüğünde ne oluyormuş ona bakalım
   PrintFormat("l_max+1=%I64d, double(l_max+1)=%.f, ulong(double(l_max+1))=%I64d",
               l_max+1,double(l_max+1),long(double(l_max+1)));
   PrintFormat("l_min-1=%I64d, double(l_min-1)=%.f, ulong(double(l_min-1))=%I64d",
               l_min-1,double(l_min-1),long(double(l_min-1)));
//--- şu sonucu al
// Bir tamsayı değeri double tipine dönüştürüldüğünde, değer, [-9223372036854774784, 9223372036854774784] aralığında olmalı
// l_max+1=9223372036854774785, double(l_max+1)=9223372036854774800, ulong(double(l_max+1))=9223372036854774784
// l_min-1=-9223372036854774785, double(l_min-1)=-9223372036854774800, ulong(double(l_min-1))=-9223372036854774784
  }

 

String Tipi için Tip Dönüşümü

string tipi basit tipler arasında en yüksek önceliğe sahiptir. Bu yüzden, işlenenlerden biri string tipinde ise, diğer işlenen de otomatik olarak string tipine dönüştürülecektir. Dizgilerde basit diyadik toplama işleminin mümkün olduğunu not ediniz. string tipinin açık tip dönüşümü, dönüştürülecek her sayısal tip için izinlidir.

Örnekler:

   string s1=1.0/8;            // ifade double tipine dönüştürüldü,
   Print("s1 = 1.0/8; ",s1);     //  sonra da string tipli hedefe,
// sonuç "0.12500000" (10 karakterli bir dizgi)
 
   string s2=NULL;             // dizginin sonlandırılması
   Print("s2 = NULL; ",s2);      // sonuç boş bir dizgi
   string s3="Ticket N"+12345; // ifade string tipine dönüştürüldü
   Print("s3 = \"Ticket N\"+12345",s3);
 
   string str1="true";
   string str2="0,255,0";
   string str3="2009.06.01";
   string str4="1.2345e2";
   Print(bool(str1));
   Print(color(str2));
   Print(datetime(str3));
   Print(double(str4));

 

Temel Sınıf İşaretçilerinden Türev Sınıf İşaretçilerine Tip Dönüşümü

Açık şekilde oluşturulmuş sınıf nesneleri, ilgili temel sınıfın nesneleri olarak da görülebilirler. Bu bazı ilginç sonuçlara yol açar. Örneğin, aynı temel sınıftan türetilmiş farklı sınıfların nesnelerinin, birbirlerinden belirgin şekilde farklı olabildikleri gerçeğini bir yana bırakırsak; bunları temel tipin nesneleri olarak gördüğümüz bir bağlantılı liste oluşturabiliriz. Ama tersi geçerli değildir: temel sınıf nesneleri otomatik olarak türetik sınıfların nesnesi olmazlar.

Temel sınıfın işaretçilerini, türetik sınıfın işaretçilerine dönüştürmek için açık dönüşüm kullanabilirsiniz. Fakat böyle bir dönüşümün kabul edilebilirliği konusunda emin olmalısınız. Çünkü, aksi durumda, önemli bir çalışma zamanı hatası gerçekleşir ve MQL5 programı durur.

dynamic_cast işlemcisi ile dinamik tip dönüşümü #

Dinamik tip dönüşümü 'dynamic_cast' işlemcisiyle gerçekleştirilir ve sadece sınıf işaretçileri için kullanılabilir. Tipin doğrulaması çalıştırma sırasında gerçekleştirilir. Yani, dynamic_cast işlemcisi kullanıldığında, derleyici tip dönüşümüne konu olan veriyi kontrol etmeyecektir. İşaretçinin, nesnenin gerçek veri tipi dışındaki tiplere dönüştürülmesinin sonucunda NULL değeri alınır.

dynamic_cast <type-id> ( expression )

type-id parametresi daha önce tanımlanan bir sınıf tipini işaret etmelidir. C++ dilinin aksine, expression işlemci tipi, void haricinde herhangi bir değeri alabilir.

Örnek:

class CBar { };
class CFoo : public CBar { };
 
void OnStart()
  {
   CBar bar;    
//--- *bar işaretçisini *foo işaretçisine dönüştürme iznimiz var
   CFoo *foo = dynamic_cast<CFoo *>(&bar); // kritik hata yok   
   Print(foo);                             // foo=NULL      
//--- Bar tipli bir nesne referansını Foo tipli bir nesneye açık yolla dönüştürme girişimi engellendi
   foo=(CFoo *)&bar;                       // kritik çalışma hatası
   Print(foo);                             // bu dizgi çalıştırılmaz
  }

Ayrıca Bakınız

Veri Tipleri