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 sabitlershort 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 char
nesneler 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
, long
ve long long
'dırchar
. Bu türler veya unsigned
ile signed
nitelenebilir ve unsigned
için unsigned int
kı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
, i
tanımlanmış ve negatif bir sayıya başlatılmış. İfade(u = i)
, atamadan önce öğesine unsigned short
dönüştürülmeye u
neden 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 double dö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 double dö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 float dö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 long dö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 long dö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 long dö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 int dönüştürülür.- Yukarıdaki koşullardan hiçbiri karşılanmazsa, her iki işlenen de türüne int dö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 int
olmasıdır. Bu nedenle, diğer işlenen olan iVal
, türüne unsigned int
dönüştürülür. Sonuç daha sonra öğesine dVal
atanır. Burada karşılanan koşul, bir işlenen türünde double
unsigned int
olduğu için çarpmanın sonucu türüne double
dö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 dVal
atanı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:
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 B
burada B
öğesinden A
türetilir. (Devralma hakkında daha fazla bilgi için bkz.Türetilmiş Sınıflar.) Ardından, türünde B
bir 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 A
işaretçisi" olarak yorumlanabilir. bObject
üyeleri (ve gibi BComponent
BMemberFunc
) türü B
için benzersizdir ve bu nedenle aracılığıyla pA
erişilemez. İşaretçi pA
yalnızca sınıfında A
tanı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ü void
iç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 volatile
volatile
olmayan 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.
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin