Implicit conversion'lar, derleyicinin kullanicidan bisey beklemeden otomatik olarak gerceklestirdigi donusumlere deniyor:
int x = 5;
float x = y;
const char* str = "hello"
std::string a = a;
struct foo
{
foo(const char* x);
};
struct goo
{
operator const char*(); // imlicit olarak const char*'a donusebiliyor
};
void hi(const char*);
goo g{};
hi(g); // implicit olarak const char* olusturuluyor
void bar(foo f);
bar("hello"); // foo otomatik construct ediliyor
Performans endiselerinden dolayi implicit donusumlerden genellikle cok hoslanmayiz. Ornegin en sondaki 'bar("hello")' cagrisi hic caktirmadan bir foo olusturuyor. Istedigimiz sey, kullanici bu tarz bir donusum istiyorsa, acik sekilde (explicit olarak) yazmasi: 'bar(foo{"hello"});'. Bu noktada kullanici aradaki gecici 'foo' nesnesinin farkinda ve belki daha verimli bir sekilde ayni isi yapabilir.
C++'da donusum islemleri (operator T() ve tek arguman alan constructor'lar) varsayilan olarak implicit calisiyor, yani kullanici gecici nesneyi explicit olarak olusturmak zorunda degil. Bunu zorunlu hale getirmek icin bahsedilen fonksyonlari 'explicit' olarak isaretleyebiliyoruz:
struct foo
{
explicit foo(const char*);
};
struct goo
{
explicit operator const char*();
};
goo g{};
hi(g); // derlenmeyecek
hi(static_cast<const char*>(g)); // tamamdir, explicit olarak donusum istedik
bar("hello"); // derlenmeyecek
bar(foo("hello")); // tamamdir, explicit olarak constructor cagrisi yaptik
Tavsiye olarak, aksi icin ozel bir sebep yoksa butun tek argumanli constructor ve donusum operatorleri explicit isaretlenmeli.
Type punning bunlardan farkli bir konu. Yukardakiler donusumu yaparken yeni bir nesne cikariyor, yani elinizde 'const char*' varsa, bundan yeni bir 'std::string' nesnesi olusturuyorsunuz ve bu tamamen guvenli bir operasyon.
Type punning durumunda, var olan bir nesneyi baska bir tipmiscesine kullaniriz. Temel olarak da 'reinterpret_cast' ve 'union'lar araciligiyla yapilir:
union fi
{
float f;
int i;
};
fi a;
a.f = 3.5f;
std::cout << a.i << '\n'; // a.f olsa sorun yok
Type punning yaptiginiz zaman genellikle elde ettiginiz objeyi kullanmaniz undefined behaviour'a yol acar. Ornegin yukardaki 'a.i' kismi aslinda C++ standardina gore anlamsiz bir ifade.
Type punning'den, eger low level biseyler yazmiyorsak kesinlikle kacinmamiz gerekir.
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]