Sadece fonksiyon aşırı yükleme için bir C ++ derleyici kullanmak kötü bir uygulama mıdır?
IMHO'nun bakış açısı, evet, ve bu dili yanıtlamak için şizofren haline gelmem gerekecek, çünkü her iki dili de seviyorum ama verimlilikle ilgisi yok, fakat daha çok dilin güvenliği ve deyimsel kullanımı gibi.
C tarafı
Bir C açısından, kodunuzu C ++ 'ı sadece aşırı fonksiyon yükünü kullanmak için gerektirecek kadar zararlı buluyorum. C ++ şablonlarıyla statik polimorfizm için kullanmadığınız sürece, tamamen farklı bir dile geçiş karşılığında kazanılan önemsiz sözdizimsel şeker. Dahası, işlevlerinizi bir dylib'e (pratik bir endişe olabilir veya olmayabilir) vermek istiyorsanız, tüm isimlendirilmiş sembollerle yaygın tüketim için artık pratik olarak bunu yapamazsınız.
C ++ Side
Bir C ++ açısından, C + gibi C işlevlerini aşırı yükleme ile kullanmamalısınız. Bu stilistik dogmatizm değil, günlük C ++ 'nın pratik kullanımı ile ilgilidir.
Normal tür C kodunuz, kopya kopyalayıcılar gibi şeyleri yasaklayan C tipi sisteme karşı çalışıyorsanız yazmak için yalnızca mantıklı ve "güvenli" olur structs
. C ++ 'ın daha zengin tip sistemiyle çalıştıktan sonra, çok değerli memset
ve günlük olmayan fonksiyonlar olan günlük fonksiyonlar memcpy
her zaman üzerine dayanmalısınız. Bunun yerine, genel olarak veba gibi önlemek istemediğiniz işlevlerdir, çünkü C ++ tipleri ile, onlara kopyalanıp karıştırılmak ve serbest bırakılmak için ham bitler ve baytlar gibi davranmamalısınız. Kodunuz memset
şu anda yalnızca ilkel ve POD UDT'leri gibi şeyler kullanıyor olsa da, herhangi birinin kullandığınız UDT'ye bir kullanıcı eklediği an (yalnızca bir tane gerektiren bir üye ekleme dahil)std::unique_ptr
üye) bu tür işlevlere veya sanal bir işleve veya bu tür bir şeye karşı, tüm normal C tarzı kodlamanızı tanımsız davranışa duyarlı hale getirir. Onu Herb Sutter'dan al:
memcpy
ve memcmp
tip sistemini ihlal eder. Kullanılması memcpy
nesneleri kopyalamak için bir fotokopi kullanarak para kazanma gibidir. Kullanma memcmp
nesneleri karşılaştırmak için kendi noktalar sayarak leoparlar karşılaştırılması gibi. Araçları ve yöntemleri işi yapmak için görünebilir, ancak kabul edilebilir bir şekilde yapmak için çok kaba. C ++ nesneleri tamamen bilgi gizlemeyle ilgilidir (muhtemelen yazılım mühendisliğinde en kârlı prensip; bkz. Madde 11): Nesneler veriyi gizler (Madde 41'e bakınız) ve bu verileri yapıcılar ve atama operatörleri aracılığıyla kopyalamak için kesin soyutlamalar tasarlar (bkz. Madde 52 ila 55) . Her şeyin üzerinde buldozerlik yapmak memcpy
ciddi bir bilgi gizliliği ihlalidir ve çoğu zaman hafıza ve kaynak sızıntılarına (en iyi ihtimalle), çökmelere (daha kötü) veya tanımsız davranışa (en kötü) - C ++ Kodlama Standartları yol açar.
Pek çok C geliştiricisi buna katılmıyor ve haklı olarak böyle davranıyor, çünkü felsefe sadece C ++ dilinde kod yazıyorsanız geçerlidir. Büyük olasılıkla vardır sen gibi işlevleri kullanırsanız çok sorunlu kod yazarken memcpy
tüm zamanların C ++ olarak inşa kodda , ancak bunu yaparsanız mükemmel para cezası C . Tipik sistemdeki farklılıklar nedeniyle, iki dil bu açıdan çok farklı. Bu ikisinin ortak özelliklerinin alt kümesine bakmak ve birisinin diğeri gibi, özellikle C ++ tarafında kullanılabileceğine inanmak çok caziptir, ancak C + kodu (veya C-- kodu) genellikle hem C'den hem de çok daha problemlidir. C ++ kodu.
Aynı şekilde, malloc
bir C tarzı bağlamda (EH anlamına gelmez) kullanamazsınız, eğer doğrudan atabilecek herhangi bir C ++ fonksiyonunu çağırabilirseniz, o zamandan beri fonksiyonunuzda kapalı bir çıkış noktanız olabilir. free
Bu hafızayı kullanmadan önce C tarzı kod yazarken etkili bir şekilde yakalayamadığınız istisna . Eğer bir ile C ++ oluşturur bir dosya var her Yani .cpp
uzantısı ya da her neyse ve benzeri şeylerin hepsini bu tür yapar malloc
, memcpy
, memset
,qsort
vb., daha sonra, sadece ilkel türlerle çalışan bir sınıfın uygulama detayı olmadığı sürece, istisnai olarak güvenli olması için hala istisna-işlem yapması gereken, bu noktada, hattın aşağısındaki problemleri soruyor. C ++ kodu yazıyorsanız yerine genellikle de ray itimat ve benzeri şeyleri kullanmak istiyor vector
, unique_ptr
, shared_ptr
, vs, ve mümkün olduğunda tüm normal C tarzı kodlama kaçının.
Jilet ve C-ışını veri türlerinde jiletlerle oynayabilmeniz ve bir takımda teminat hasarı oluşturmaya eğilimli olmadan bitleri ve baytları ile oynayabilmenizin nedeni (yine de kendinize gerçekten zarar verebilmenize rağmen) türleri yapabilir , fakat asla yapamayacakları şey yüzünden. C'nin tip sistemini, istisnaların ele alınmasının yanı sıra, ciro, dtors ve vtables gibi C ++ özelliklerini içerecek şekilde genişlettiğiniz an, tüm deyimsel C kodları şu anda olduğundan çok daha tehlikeli hale getirilecek ve yeni bir tür kod göreceksiniz. C ++ 'da gördüğünüz gibi tamamen farklı bir kodlama tarzını teşvik edecek bir felsefe ve zihniyet gelişimi, artık bir RAII-uyumlu kaynağa zıt olarak hafızayı yöneten bir sınıf için ham bir işaretçi yanlış uygulaması bile kullanmayı düşünmektedir unique_ptr
. Bu zihniyet mutlak bir güvenlik duygusundan çıkmadı. C ++ 'nın özellikle tür sistemi aracılığıyla izin verdiği durumlar dışında istisna işleme gibi özelliklere karşı özellikle güvenli olması gerekenlerden doğdu .
İstisna-Emniyet
Yine, C ++ ülkesinde olduğunuz an, insanlar kodunuzun istisnai güvenli olmasını bekler. İnsanlar std::vector, dynamic_cast, unique_ptr, shared_ptr
, kodunuz zaten "sözde" C ++ olduğundan zararsız olduğuna inandığından, kodunuzu önceden yazılmış veya dolaylı olarak C ++ 'da derlendiği ve kodunuz tarafından doğrudan veya dolaylı olarak adlandırılan kodda kullandığı gibi kodunuzu gelecekte kullanabilirler . kodu. Bu noktada, işlerin atılma şansı ile karşı karşıya kalmamız gerekiyor ve sonra böyle güzel ve güzel C kodu aldığınızda:
int some_func(int n, ...)
{
int* x = calloc(n, sizeof(int));
if (x)
{
f(n, x); // some function which, now being a C++ function, may
// throw today or in the future.
...
free(x);
return success;
}
return fail;
}
... şimdi bozuldu. İstisnai güvenli olması için yeniden yazılması gerekir:
int some_func(int n, ...)
{
int* x = calloc(n, sizeof(int));
if (x)
{
try
{
f(n, x); // some function which, now being a C++ function, may
// throw today or in the future (maybe someone used
// std::vector inside of it).
}
catch (...)
{
free(x);
throw;
}
...
free(x);
return success;
}
return fail;
}
Brüt! Bu nedenle çoğu C ++ geliştiricisi bunun yerine talep eder:
void some_func(int n, ...)
{
vector<int> x(n);
f(x); // some function which, now being a C++ function, may throw today
// or in the future.
}
Yukarıdaki, C ++ geliştiricilerin genel olarak onaylayacağı türden RAII uyumlu istisnai güvenlik kodudur; çünkü işlev, hangi kod satırının bir dolaylı olarak kapalı bir çıkışı tetiklediğini hiçbiri sızdırmaz throw
.
Dil Seç
C ++ 'nın tip sistemini ve felsefesini RAII, istisna güvenlik, şablonlar, OOP vb. İle benimsemeli veya büyük ölçüde ham bitler ve baytlar etrafında dönen C'yi kucaklamalısınız. Bu iki dil arasında kutsal olmayan bir evlilik yapmamalı ve onları bir araya getirmek yerine çok farklı muamele görmeleri için farklı dillere ayırmamalısınız.
Bu diller seninle evlenmek istiyor. Genelde her ikisi ile de buluşmak ve eğlenmek yerine bir tane seçmelisin. Ya da benim gibi bir çok eşli olabilir ve ikisiyle de evlenebilirsiniz, ancak birbirleriyle zaman geçirirken düşüncelerinizi tamamen değiştirmelisiniz ve birbirleriyle iyi ayrılmamalarını sağlayın.
İkili boyutu
Merak ettim, hemen şimdi ücretsiz liste uygulamamı ve kıyaslamamı almaya ve bunu gerçekten merak ettiğimden beri C ++ 'a taşımayı denedim:
[...] C için nasıl görüneceğini bilmiyorum çünkü C derleyicisini kullanmıyordum.
... ve ikilik boyutun sadece C ++ 'da inşa edilip edilmeyeceğini bilmek istedi. Kaçak yerin her yerine açık yayınlar atmamı istedi (nedenlerden biri, C'deki tüm ayırıcılar ve veri yapıları gibi düşük seviyeli şeyler yazmaktan daha iyi bir şeydi) ama sadece bir dakika sürdü.
C ile bina ve diyelim ki, kullanmak arasındaki sadece fark - Bu sadece basit bir konsol uygulaması için ve ++ özelliklerini, hatta operatör aşırı yükleme herhangi C'yi kullanmak vermedi kodunu içeren bir MSVC 64 bit sürüm derlemesi karşılaştırıyordum <cstdlib>
yerine <stdlib.h>
ve Bunun gibi şeyler, ancak ikili boyut için sıfır fark yarattığını görünce şaşırdım!
İkili 9,728
C 9,278
olarak oluşturulduğunda bayt , aynı şekilde C ++ kodu olarak derlendiğinde bayttı. Aslında bunu beklemiyordum. EH gibi şeylerin orada en azından biraz ekleyeceğini düşündüm (en azından yüz byte farklı olacağını düşünmüştüm), ancak muhtemelen ben sadece EH ile ilgili talimatlar eklemeye gerek olmadığını anlayabiliyordum. C standart kütüphanesini kullanarak hiçbir şey atmaz. Bir şey düşündümRTTI gibi her iki şekilde de ikili boyuta biraz ekleyecekti. Neyse, bunu görmek çok güzeldi. Tabii ki bu bir sonuçtan genelleştirmen gerektiğini düşünmüyorum, ama en azından beni biraz etkiledi. Ayrıca kıyaslamalar üzerinde hiçbir etkisi olmadı ve doğal olarak, çünkü aynı sonuçta elde edilen ikili boyutun aynı sonuçta elde edilen makine talimatları anlamına geldiğini hayal ediyorum.
Bununla birlikte, yukarıda belirtilen güvenlik ve mühendislik konularında ikili büyüklük ile kim ilgileniyor? Öyleyse yine bir dil seçin ve onu bastarize etmeye çalışmak yerine felsefesini benimseyin; Ben de bunu tavsiye ediyorum.
//
yorum yapabilmem için sadece C özelliklerini kullanan bir proje için kullandım . İşe yararsa, neden olmasın?