Aracılığıyla paylaş


Standart dönüşümler

C++ dili, temel türleri arasındaki dönüştürmeleri tanımlar. Ayrıca işaretçi, başvuru ve işaretçiden üyeye türetilmiş türler için dönüştürmeleri tanımlar. Bu dönüştürmeler standart dönüştürmeler olarak adlandırılır.

Bu bölümde aşağıdaki standart dönüştürmeler ele alınmaktadır:

  • İntegral yükseltmeler

  • İntegral dönüştürmeler

  • Kayan dönüştürmeler

  • Kayan ve tam sayı dönüştürmeleri

  • Aritmetik dönüştürmeler

  • İşaretçi Dönüştürmeler

  • Başvuru dönüştürmeleri

  • Üyeye işaretçi dönüştürmeleri

    Dekont

    Kullanıcı tanımlı türler kendi dönüştürmelerini belirtebilir. Kullanıcı tanımlı türlerin dönüştürülmesi Oluşturucular ve Dönüştürmeler bölümünde ele alınmıştır.

Aşağıdaki kod dönüştürmelere neden olur (bu örnekte, tam sayı yükseltmeleri):

long  long_num1, long_num2;
int   int_num;

// int_num promoted to type long prior to assignment.
long_num1 = int_num;

// int_num promoted to type long prior to multiplication.
long_num2 = int_num * long_num2;

Dönüştürmenin sonucu, yalnızca bir başvuru türü üretirse bir l değeridir. Örneğin, olarak bildirilen operator int&() kullanıcı tanımlı dönüştürme bir başvuru döndürür ve bir l değeridir. Ancak, olarak operator int() bildirilen dönüştürme bir nesne döndürür ve bir l değeri değildir.

İntegral yükseltmeler

Bir integral türü nesneleri başka bir daha geniş tamsayıyı türüne dönüştürülebilir, yani daha büyük bir değer kümesini temsil eden bir tür. Bu genişletme dönüştürme türüne integral yükseltme denir. İntegral yükseltme ile, başka bir tam sayı türünün kullanabildiği her yerde bir ifadede aşağıdaki türleri kullanabilirsiniz:

  • ve türüne char ait nesneler, değişmez değerler ve sabitler short int

  • Numaralandırma türleri

  • int bit alanları

  • Numaralandırıcılar

Yükseltmeden sonraki değerin, yükseltmeden önceki değerle aynı olacağı garanti edile C++ yükseltmeleri "değer koruyucudur". Değer koruma yükseltmelerinde, özgün türün tam aralığını temsil edebilirseint, daha kısa integral türlerine sahip nesneler (bit alanları veya türündeki charnesneler gibi) türe int yükseltilir. int Değer aralığının tamamını gösteremiyorsa, nesnesi yazacak unsigned intşekilde yükseltilir. Bu strateji Standart C tarafından kullanılan stratejiyle aynı olsa da, değer koruma dönüştürmeleri nesnenin "imzalılığını" korumaz.

Değer korumalı yükseltmeler ve işaretli durumu koruyan yükseltmeler normalde aynı sonuçları verir. Ancak, yükseltilen nesne şu şekilde görünürse farklı sonuçlar üretebilir:

  • , , %, , /=, %=, <, <=, >veya işleneni />=

    Bu işleçler sonucu belirlemek için işareti kullanırlar. Değer koruma ve imza koruma yükseltmeleri, bu işlenenlere uygulandığında farklı sonuçlar üretir.

  • veya'ın sol işleneni >>>>=

    Bu işleçler, bir vardiya işleminde imzalı ve imzasız miktarları farklı şekilde ele alır. İmzalı miktarlar için, sağ kaydırma işlemi işaret bitini boşaltılmış bit konumlarına yayarken, boşaltılan bit konumları işaretsiz miktarlarla sıfır doldurulur.

  • Aşırı yüklenmiş bir işlevin bağımsız değişkeni veya aşırı yüklenmiş işlecin işleneni, bağımsız değişken eşleştirme için işlenen türünün imzalılığına bağlıdır. Aşırı yüklenmiş işleçleri tanımlama hakkında daha fazla bilgi için bkz . Aşırı yüklenmiş işleçler.

İntegral dönüştürmeler

İntegral dönüştürmeler , tam sayı türleri arasındaki dönüştürmelerdir. İntegral türleri , short (veya short int), int, longve long long'dırchar. Bu türler veya unsignedile signed nitelenebilir ve unsigned için unsigned intkısaltma olarak kullanılabilir.

İmzasız olarak imzalandı

İşaretli integral türlerindeki nesneler, ilgili işaretsiz türlere dönüştürülebilir. Bu dönüştürmeler gerçekleştiğinde gerçek bit düzeni değişmez. Ancak, verilerin yorumu değişir. Bu kodu göz önünde bulundurun:

#include <iostream>

using namespace std;
int main()
{
    short  i = -3;
    unsigned short u;

    cout << (u = i) << "\n";
}
// Output: 65533

Yukarıdaki örnekte, bir signed short, itanımlanmış ve negatif bir sayıya başlatılmış. İfade(u = i), atamadan önce öğesine unsigned short dönüştürülmeye uneden oluri.

İmzalanmamış

İşaretsiz integral türlerindeki nesneler, ilgili işaretli türlere dönüştürülebilir. Ancak, imzalanmamış değer imzalı türün temsil edilebilir aralığının dışındaysa, aşağıdaki örnekte gösterildiği gibi sonuç doğru değere sahip olmaz:

#include <iostream>

using namespace std;
int main()
{
short  i;
unsigned short u = 65533;

cout << (i = u) << "\n";
}
//Output: -3

Yukarıdaki örnekte, u ifadesini (i = u)değerlendirmek için imzalı bir miktara dönüştürülmesi gereken bir integral nesnesidirunsigned short. değeri içinde düzgün bir signed shortşekilde temsil edilemediğinden, veriler gösterildiği gibi yanlış yorumlanır.

Kayan nokta dönüştürmeleri

Kayan türdeki bir nesne güvenli bir şekilde daha hassas bir kayan türe dönüştürülebilir; başka bir deyişle dönüştürme, anlam kaybına neden olmaz. Örneğin, öğesinden float veya double öğesinden double kime long double dönüştürmeleri güvenlidir ve değer değişmez.

Kayan türdeki bir nesne, bu türle temsil edilebilen bir aralıktaysa daha az kesin bir türe dönüştürülebilir. (Bkz. Kayan tür aralıkları için Kayan Sınırlar .) Özgün değer tam olarak temsil edilemiyorsa, sonraki daha yüksek veya daha düşük temsil edilebilir değere dönüştürülebilir. Böyle bir değer yoksa sonuç tanımsız olur. Aşağıdaki örneği inceleyin:

cout << (float)1E300 << endl;

Türe float göre temsil edilebilen en büyük değer 3,402823466E38'dir ve bu değer 1E300'den çok daha küçük bir sayıdır. Bu nedenle sayı sonsuzluğa dönüştürülür ve sonuç "inf" olur.

İntegral ve kayan nokta türleri arasındaki dönüştürmeler

Belirli ifadeler, kayan türde nesneleri integral türlerine dönüştürebilirler veya tam tersi olabilir. İntegral türündeki bir nesne kayan bir türe dönüştürüldüğünde ve özgün değer tam olarak temsil edilemiyorsa, sonuç bir sonraki daha yüksek veya bir sonraki düşük temsil edilebilir değer olur.

Kayan türdeki bir nesne tamsayı türüne dönüştürüldüğünde kesirli bölüm kesilir veya sıfıra yuvarlanır. 1,3 gibi bir sayı 1'e, -1,3 ise -1'e dönüştürülür. Kesilen değer en yüksek temsil edilebilir değerden yüksekse veya en düşük temsil edilebilir değerden düşükse sonuç tanımlanmamış olur.

Aritmetik dönüştürmeler

Birçok ikili işleç (İkili işleçli ifadeler bölümünde anlatılmaktadır) işlenenlerin dönüştürülmelerine neden olur ve sonuçları aynı şekilde verir. Bu işleçlerin neden olduğu dönüştürmeler, normal aritmetik dönüştürmeler olarak adlandırılır. Farklı yerel türlere sahip işlenenlerin aritmetik dönüştürmeleri aşağıdaki tabloda gösterildiği gibi yapılır. Typedef türleri, temel yerel türlerine göre davranır.

Tür dönüştürme koşulları

Karşılandığı Koşullar Dönüştürme
her iki işlenen de türündedir long double. Diğer işlenen türüne long doubledönüştürülür.
Önceki koşul karşılanmadı ve her iki işlenen de türündedir double. Diğer işlenen türüne doubledönüştürülür.
Önceki koşullar karşılanmaz ve her iki işlenen de türündedir float. Diğer işlenen türüne floatdönüştürülür.
Önceki koşullar karşılanmamıştır (işlenenlerden hiçbiri kayan türlerden değil). İşlenenler aşağıdaki gibi integral yükseltmeleri alır:

- İşlenenlerden biri türündeyse unsigned long, diğer işlenen türüne unsigned longdönüştürülür.
- Önceki koşul karşılanmazsa ve işlenenlerden biri türündeyse long ve diğeri türündeyse unsigned int, her iki işlenen de türüne unsigned longdönüştürülür.
- Yukarıdaki iki koşul karşılanmazsa ve işlenenlerden biri türündeyse long, diğer işlenen türüne longdönüştürülür.
- Yukarıdaki üç koşul karşılanmazsa ve işlenenlerden biri türündeyse unsigned int, diğer işlenen türüne unsigned intdönüştürülür.
- Yukarıdaki koşullardan hiçbiri karşılanmazsa, her iki işlenen de türüne intdönüştürülür.

Aşağıdaki kodda, tabloda açıklanan dönüştürme kuralları gösterilmektedir:

double dVal;
float fVal;
int iVal;
unsigned long ulVal;

int main() {
   // iVal converted to unsigned long
   // result of multiplication converted to double
   dVal = iVal * ulVal;

   // ulVal converted to float
   // result of addition converted to double
   dVal = ulVal + fVal;
}

Yukarıdaki örnekte bulunan ilk deyim, iki integral türü olan iVal ve ulVal'ın çarpımını göstermektedir. Karşılanacak koşul, hiçbir işlenenin kayan türde ve bir işlenenin türünde unsigned intolmasıdır. Bu nedenle, diğer işlenen olan iVal, türüne unsigned intdönüştürülür. Sonuç daha sonra öğesine dValatanır. Burada karşılanan koşul, bir işlenen türünde doubleunsigned int olduğu için çarpmanın sonucu türüne doubledönüştürülür.

Yukarıdaki örnekteki ikinci deyim, ve float integral türünün eklenmesini gösterir: fVal ve ulVal. Değişken ulVal türe float dönüştürülür (tablodaki üçüncü koşul). Toplamanın sonucu türüne double dönüştürülür (tablodaki ikinci koşul) ve öğesine dValatanır.

İşaretçi Dönüştürmeler

İşaretçiler atama, başlatma, karşılaştırma ve diğer ifadeler sırasında dönüştürülebilir.

Sınıfların işaretçisi

Bir sınıfa işaretçinin temel sınıfa işaretçiye dönüştürülebileceği iki durum vardır.

İlk durum, belirtilen temel sınıfın erişilebilir olduğu ve dönüştürmenin kesin olduğu durumlardır. Belirsiz temel sınıf başvuruları hakkında daha fazla bilgi için bkz . Birden çok temel sınıf.

Temel sınıfın erişilebilir olup olmadığı, türetmede kullanılan devralma türüne bağlıdır. Aşağıdaki şekilde gösterilen devralmayı göz önünde bulundurun:

Diagram showing an inheritance graph and base class accessibility.

Diyagramda A temel sınıfı gösterilmektedir. B sınıfı özel korumalı genel aracılığıyla A'dan devralır. C sınıfı, genel B aracılığıyla B'den devralır.

Temel sınıf erişilebilirliği gösteren devralma grafiği

Aşağıdaki tabloda, şekilde gösterilen durum için temel sınıf erişilebilirliği gösterilmektedir.

İşlev Türü Türev Dönüştürme:

B* yasal mı A* ?
Dış (sınıf kapsamlı değil) işlevi Özel No
Korumalı No
Sunulabilir Evet
B üye işlevi (B kapsamında) Özel Evet
Korumalı Evet
Sunulabilir Evet
C üye işlevi (C kapsamında) Özel No
Korumalı Evet
Sunulabilir Evet

Bir sınıfa yönelik işaretçinin temel sınıfa yönelik bir işaretçiye dönüştürülebildiği ikinci durum, açık bir tür dönüştürmesi kullanmanızdır. Açık tür dönüştürmeleri hakkında daha fazla bilgi için bkz . Açık tür dönüştürme işleci.

Böyle bir dönüştürmenin sonucu, nesnenin temel sınıf tarafından tamamen açıklanan bölümü olan alt nesneye bir işaretçidir.

Aşağıdaki kod iki A sınıf tanımlar ve Bburada B öğesinden Atüretilir. (Devralma hakkında daha fazla bilgi için bkz.Türetilmiş Sınıflar.) Ardından, türünde Bbir nesnesi ve nesneye işaret eden iki işaretçi (pA ve pB) tanımlarbObject.

// C2039 expected
class A
{
public:
    int AComponent;
    int AMemberFunc();
};

class B : public A
{
public:
    int BComponent;
    int BMemberFunc();
};
int main()
{
   B bObject;
   A *pA = &bObject;
   B *pB = &bObject;

   pA->AMemberFunc();   // OK in class A
   pB->AMemberFunc();   // OK: inherited from class A
   pA->BMemberFunc();   // Error: not in class A
}

İşaretçi pA türündedir A *ve "türünde bir nesnenin Aişaretçisi" olarak yorumlanabilir. bObject üyeleri (ve gibi BComponentBMemberFunc) türü B için benzersizdir ve bu nedenle aracılığıyla pAerişilemez. İşaretçi pA yalnızca sınıfında Atanımlanan nesnenin bu özelliklerine (üye işlevleri ve verileri) erişmesine izin verir.

İşlev işaretçisi

bir işlevin işaretçisi, tür void *bu işaretçiyi tutacak kadar büyükse türüne void * dönüştürülebilir.

Geçersiz kılma işaretçisi

Tür işaretçileri başka bir türe void işaretçilere dönüştürülebilir, ancak yalnızca açık tür ataması ile (C'de aksine). Herhangi bir türün işaretçisi, türü voidiçin örtük olarak bir işaretçiye dönüştürülebilir. Bir türün tamamlanmamış nesnesine yönelik işaretçi, işaretçiye void (örtük olarak) ve geri (açıkça) dönüştürülebilir. Böyle bir dönüştürmenin sonucu, özgün işaretçinin değerine eşittir. Bir nesne bildirilirse tamamlanmamış olarak kabul edilir, ancak boyutunu veya temel sınıfını belirlemek için yeterli bilgi yoktur.

Olmayan veya volatile örtük olarak türünde void *bir işaretçiye dönüştürülebilen herhangi bir nesnenin const işaretçisi.

const ve volatile işaretçiler

C++ veya türünden const veya volatilevolatileolmayan const bir türe standart dönüştürme sağlamaz. Ancak, herhangi bir dönüştürme türü açık tür atamaları (güvenli olmayan dönüştürmeler dahil) kullanılarak belirtilebilir.

Dekont

Statik üyelere yönelik işaretçiler dışında üyelere yönelik C++ işaretçileri normal işaretçilerden farklıdır ve aynı standart dönüştürmelere sahip değildir. Statik üyelerin işaretçileri normal işaretçilerdir ve normal işaretçilerle aynı dönüştürmelere sahiptir.

null işaretçi dönüştürmeleri

Sıfır olarak değerlendirilen bir tamsayı sabit ifadesi veya işaretçi türüne türe türeyen bir ifade, null işaretçi olarak adlandırılan bir işaretçiye dönüştürülür. Bu işaretçi her zaman eşit olmayan bir işaretçiyi geçerli bir nesne veya işlevle karşılaştırır. Özel durum, aynı uzaklığı olan ve yine de farklı nesnelere işaret eden tabanlı nesnelere yönelik işaretçilerdir.

C++11'de nullptr türü, C stili null işaretçi için tercih edilmelidir.

İşaretçi ifadesi dönüştürmeleri

Dizi türündeki bir ifade, aynı türden bir işaretçiye dönüştürülebilir. Dönüştürme işleminin sonucunda, ilk dizi öğesinin işaretçisi elde edilir. Aşağıdaki örnekte, böyle bir dönüştürme gösterilmektedir:

char szPath[_MAX_PATH]; // Array of type char.
char *pszPath = szPath; // Equals &szPath[0].

Belirli bir türü döndüren bir işlevle sonuçlanan ifade, aşağıdakiler haricinde bu türü döndüren bir işlevin işaretçisine dönüştürülür:

  • İfade, işlecin adresi (&) için işlenen olarak kullanılır.

  • İfade, işlev çağrısı işlecinin bir işleneni olarak kullanılıyorsa.

Başvuru dönüştürmeleri

Bir sınıf başvurusu, aşağıdaki durumlarda bir temel sınıf başvurusuna dönüştürülebilir:

  • Belirtilen temel sınıfa erişilebilir.

  • Dönüştürme belirsiz değildir. (Belirsiz temel sınıf başvuruları hakkında daha fazla bilgi için bkz. Birden çok temel sınıf.)

Dönüştürmenin sonucu temel sınıfı temsil eden alt nesne için bir işaretçidir.

Üye işaretçisi

Sınıf üyeleri için işaretçiler; atama, başlatma, karşılaştırma ve diğer ifadeler sırasında dönüştürülebilir. Bu bölüm aşağıdaki üye işaretçisi dönüştürmelerini açıklar:

Temel sınıf üyesi işaretçisi

Aşağıdaki koşullar karşılandığında, temel sınıfın üyesinin işaretçisi sınıfın kendisinden üretilmiş üyesinin işaretçisine dönüştürülebilir:

  • Türetilmiş sınıfın işaretçisinden temel sınıf işaretçisine ters dönüştürme erişilebilirdir.

  • Türetilmiş sınıf, temel sınıftan sanal olarak devralmaz.

Sol işlenen üyenin bir işaretçisi olduğunda, sağ işlenen üye işaretçisi türünde veya 0 olarak değerlendirilen sabit bir ifade olmalıdır. Bu atama, yalnızca aşağıdaki durumlarda geçerlidir:

  • Sağ işlenen, sol işlenenle aynı sınıfta olan üyenin bir işaretçisidir.

  • Sol işlenen, sağ işlenenin sınıfından genel ve açık olarak türetilmiş sınıfın üyesinin bir işaretçisidir.

üye dönüştürmeleri için null işaretçi

Sıfır olarak değerlendirilen tamsayı sabit ifadesi null işaretçiye dönüştürülür. Bu işaretçi her zaman eşit olmayan bir işaretçiyi geçerli bir nesne veya işlevle karşılaştırır. Özel durum, aynı uzaklığı olan ve yine de farklı nesnelere işaret eden tabanlı nesnelere yönelik işaretçilerdir.

Aşağıdaki kodda, i sınıfındaki A üyesinin işaretçisinin tanımı gösterilmektedir. pai işaretçisi, null işaretçi olan 0 ile başlatılır.

class A
{
public:
int i;
};

int A::*pai = 0;

int main()
{
}

Ayrıca bkz.

C++ dil başvurusu