c tarzı atma veya c ++ tarzı atma


21

Peki, ne kullanıyorsun?

int anInt = (int)aFloat;

veya

int anInt = static_cast<int>(aFloat);
// and its brethren

Ve daha da önemlisi, neden?

Yanıtlar:


45

İlk olarak, bu çizgilerin eşdeğer olmadığını anlayın .

int* anInt = (int*)aFloat; // is equivalent to

int* anInt = reinterpret_cast<int*>(aFloat); 

Burada olan şey, programcının derleyiciden döküm yapmak için elinden geleni yapmasını istemesidir.

Fark önemlidir çünkü static_cast sadece dönüştürmek için "güvenli" bir taban türü isteyecektir, burada reinterpret_cast herhangi bir şeye dönüşecektir, muhtemelen sadece istenen nesnenin hafızası üzerinde istenen hafıza düzenini eşleyerek.

Dolayısıyla, "filtre" aynı olmadığından, belirli bir döküm kullanmak C dökümünü kullanmaktan daha açık ve güvenlidir, derleyiciye (veya dynamic_cast kullanıyorsanız çalışma zamanı impl.) Güvenirseniz, nerede yanlış bir şey yaptığınızı size söyler , avong C döküm ve reinterepret_cast ile.

Artık bu daha açık, başka bir şey daha var: static_cast, reinterpret_cast, const_cast ve dynamic_cast'in aranması daha kolay .

Ve nihai nokta: çirkinler . Bu aranıyor. Potansiyel olarak buggy kodu, kod kokuları, hatalara neden olabilecek bariz "hileler", çirkin görünümle ilişkilendirildiğinde izlenmesi daha kolaydır. Kötü kod çirkin olmalı .

Bu "tasarım gereği". Ve bu, geliştiricinin işleri daha iyi yapabileceğini (gerçekten gerekli değilse, atmalardan tamamen kaçınarak) ve nerede iyi olduğunu bilmesine izin verir, ancak nerede olduğunu çirkin olarak işaretleyerek kodda "belgelenir".

Yeni stil dökümünü tanıtmanın ikincil bir nedeni, C stili dökümlerin bir programda fark edilmesinin çok zor olmasıydı. Örneğin, sıradan bir editör veya kelime işlemci kullanarak yayınları kolayca arayamazsınız. C tipi dökümlerin bu görünmezliği özellikle talihsizdir çünkü potansiyel olarak zararlıdırlar. Çirkin bir operasyonun çirkin bir sözdizimsel formu olmalıdır. Bu gözlem, yeni tarz dökümler için sözdizimini seçme nedeninin bir parçasıydı. Başka bir neden, yeni stil dökümlerin şablon gösterimi ile eşleşmesiydi, böylece programcılar kendi dökümlerini, özellikle çalışma zamanı kontrol edilen dökümlerini yazabilirler.

Belki, static_cast yazması çok çirkin ve göreceli olarak zor olduğundan, birini kullanmadan önce iki kez düşünmeniz daha olasıdır? Bu iyi olurdu, çünkü dökümler gerçekten modern C ++ 'da çoğunlukla önlenebilir.

Kaynak: Bjarne Stroustrup (C ++ yaratıcısı)


2
Birkaç puanım olsaydı bunu küçümserdim, ama ne yazık ki yapamam. c stili yayınlar reinterpret_cast ile eşdeğer DEĞİLDİR. Düşünün reinterpret_cast<int>(double);. C-tarzı bir döküm ile bir int'e bir çifte döküm yapmak tamamen mümkündür, ancak reinterpret_cast ile yapmak mümkün değildir. Timbo'nun bunu size işaret ettiğini görüyorum ve düzeltebileceğinizi söylediniz, ancak dört yıl sonra yanlış kalıyor. Yine de düzeltilmiş olsaydı, sizi aldatırım, çünkü bir döküm kullanmanız için mükemmel geçerli nedenler vardır. İşte daha iyi bir cevap: stackoverflow.com/a/332086/3878168
Yay295

36

C ++ yayınları daha kısıtlayıcıdır (bu nedenle niyetinizi daha iyi ifade edin ve kod incelemesini kolaylaştırın vb.). İhtiyacınız olursa aramak da çok daha kolay.


10
... ve niyet ettiklerinizi yapmaları daha olasıdır. ;-)
Macke

7
Ve onlar yazmak için çok daha fazla, sadece dökümleri olmadan türlerinizi doğru almak için bir neden daha verir.
Michael Kohne

7
Ve çirkin bir özellik olarak, kodda nerede iyileştirme noktaları veya belgeleme gerektirebilecek özel durumlar olabileceğini açıkça ortaya koyuyorlar. - edit: wow sadece bu soruyu da cevapladığımı keşfettim! XD
Klaim

Şimdi neden onları aramak isteyeyim?
Deduplicator

@Deduplicator Kod tabanındaki yayınların nerede olduğunu bilmek isteyebileceğiniz birçok neden vardır. Örneğin dökümle ilişkilendirilebilecek hataları avlarken (özellikle platformlar arası geliştirme yaparken).
Klaim

13

Seçenek C: bir "C ++ tarzı" döküm, çünkü bir yapıdan ayırt edilemez:

int anInt = int(aFloat);

ya da:

int anInt(aFloat);

Bunun yanı sıra, iyi anlaşılmış ilkelleri olan bu önemsiz durumlar dışında, C stili dökümler üzerinde x_cast <> kullanmayı tercih ediyorum. Bunun üç nedeni vardır:

  • Programcının gerçekleştirmeye çalıştığı işlemi daha dar bir şekilde tanımlarlar.

  • C stili dökümlerin yapamayacağı eylemleri gerçekleştirebilirler (özellikle, birden fazla miras zincirinin dalları arasında çapraz geçiş yapabilen dynamic_cast <> durumunda).

  • Onlar çirkin . Programcının tip sistemine karşı çalıştığını yüksek sesle ilan ederler. Bu durumda, iyi bir şey.


7

C dilinde kod yazıyorsanız bir C döküm kullanın. C ++ ile yazıyorsanız, bir C ++ cast kullanın.

Çoğu döküm uygun tip güvenliği bozarken, C ++ olanlar daha kısıtlayıcıdır ve bu nedenle C dökümüyle olduğundan daha az tip güvensizsiniz.

Ben aşırı yük zorlamak rağmen (T *) NULL kullanarak birini tolere edebilir ...


7

C / C ++ - tarzı döküm hakkında birkaç kural var:

  1. Bir sabitin kaldırılması daima a kullanmalıdır const_cast. Açık nedenlerden dolayı. Ne yazık ki, klavyenin uzanmasına ve programcının parmağını kırmasına neden olan bir sabitin kaldırılmasına ilişkin kuralım onaylanmadı.
  2. Programcıların metale inerken aldıkları bit manipülasyon tarzı parıltılardan herhangi biri kullanmalıdır reinterpret_cast. Gerçekten C'nin sahip olmadığı türden bir döküm: bu tamsayı'nın bitlerinin aslında bir şamandıra biti gibi davran. Bu gibi tatsızlığı önler (int)(*(int*)(&floatVar)).
  3. " dynamic_cast" Kelimelerini yazarsanız , polimorfik sınıf hiyerarşinizi ve tasarımınızı durdurun ve yeniden değerlendirin. Bu kelimeleri silene kadar sınıf hiyerarşinizin tasarımını yeniden değerlendirmeye devam edin.
  4. Rahatsız etme static_cast.

# 4'ün ardındaki mantık basitçe bunun önemli olmamasıdır. Diğer kurallara uymayan koşullar ya açık ya da gerçekten düşük düzeydedir. İnt-to-float gibi basit türlerin iyi anlaşılmış bir dönüşümü için özel sözdizimi gerekmez. Ve eğer bir şeyin derin, çirkin bağırsaklarına düştüyseniz, bir şeyin derin, çirkin bağırsaklarına düştünüz. Dişler, pençeler ve ateşin hemen hemen onu vermiş olması nedeniyle "burada ejderhalar" olduğuna dikkat çekmeye gerek yoktur.


1
dynamic_castson derece geçerli bir araçtır. Nadiren yararlı, itiraf edeceğim, ancak küresel değişkenler gibi şeylerin Şeytanından uzak. Bununla birlikte, öncelikle, sizi caydırdım çünkü C tarzı dökümlerin kullanımı ya da kullanılmamasıyla ilgili soruya cevap vermediniz .
DeadMG

2
@DeadMG: C tarzı oyuncular hakkında konuşmuştum. Son paragrafın tamamı, C stili dökümleri static_cast lehine haklı çıkarır.
Nicol Bolas

"Ne yazık ki, klavyenin uzanmasına ve programcının parmağını kırmasına neden olan bir sabitin kaldırılmasına ilişkin kuralım onaylanmadı." Teknik olarak derleyicinin bunu yapması yasaldır. Derleyicinin iblislerin burnundan uçması yasaldır .
Pharap


3

Gerçekten hangi dilde çalıştığımıza bağlı, çünkü ne dediklerini biliyorsunuz: Roma'da Roman konuşuyor. Bu yüzden C programlıyorsam, C özelliklerini max için kullanmaya çalışıyorum, ancak C ++ programlıyorsam devam edin ve bazı insanlar bu yaklaşımı sevmese bile max C ++ özelliklerini kullanıyorum çünkü onlar kod "daha az taşınabilir" yapar, umurumda değil, ben C ++ ve programlama C ++, ve kod derlemek için tamamen C ++ uyumlu bir derleyici gerekir, aksi takdirde farklı bir şey ile çalışacağını söylüyorlar ilk başta.


Gerçekten C;
Steve314

3

static_cast, vb. şablonlarda kullanıldığında C stili dökümlerle ilgili sorunlar nedeniyle icat edildi. Bir şablon yazıyorsanız veya kodunuz daha sonra bir şablona dönüştürülebilirse, C ++ stili dökümler kullanmak iyi bir fikirdir. Bunun nedeni, C ++ stili ifadelerin daha iyi ifade etme amacı taşımasıdır, bu nedenle C stili dökümlerin yanlış bir şey yapacağı durumlarda beklenen sonuçları verecektir (şablon parametreleri olarak belirli türler verilir).

Bunun dışında, onlara ihtiyacı olan belirli bir sorun varsa C ++ tarzı dökümleri kullan diyorum - dynamic_cast en yaygın olanıdır, ancak bu muhtemelen her gün bir şey değildir.

Başka bir şey ve C tarzı bir döküm biraz daha az dağınıklık ve okunabilirliğe yardımcı olabilir veya belki de okuyucunun bu döküm stiline ne kadar aşina olduğuna bağlı olmayabilir. Benim görüşüme göre çok önemli değil, çoğunlukla kişisel bir tercih şey, ancak bazı insanlar C stilini sevmiyorsa şaşırmayın.

Son not - eğer bu çok önemli bir şey söz konusu ise, büyük olasılıkla yanlış bir şey yapıyorsunuzdur. Bazı durumlarda bunun istisnaları vardır, ancak çoğu üst düzey kodun çok sayıda (varsa) dökümüne ihtiyacı olmamalıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.