Sadece fonksiyon aşırı yükleme için bir C ++ derleyici kullanmak kötü bir uygulama mıdır?


60

Bu yüzden belirli bir işlemci için C kullanarak bir yazılım tasarımı üzerinde çalışıyorum. Araç kiti C ve C ++ 'ları derleme becerisine sahiptir. Yaptıklarım için, bu ortamda dinamik bir bellek ayırma işlemi mevcut değil ve program genel olarak oldukça basit. Cihazın neredeyse hiçbir işlemci gücüne veya kaynağına sahip olduğundan bahsetmiyorum. Herhangi bir C ++ kullanmak için gerçekten güçlü bir ihtiyaç yoktur.

Olduğu söyleniyor, işlev aşırı yükleme yaptığım birkaç yer var (C ++ özelliği). Birkaç farklı türde veri göndermem gerekiyor ve printfstil formatını bir çeşit %s(veya her neyse) argümanla kullanmak istemiyorum . Bunu yapan C ++ derleyicisine erişimi olmayan bazı insanlar gördüm printf, ama benim durumumda C ++ desteği var.

Şimdi, başlamak için neden bir işlevi aşırı yüklemem gerektiği sorusunu alabileceğime eminim. Bu yüzden şimdi cevap vermeye çalışacağım. Farklı veri tiplerini seri bir porttan iletmem gerekiyor, bu yüzden aşağıdaki veri tiplerini ileten birkaç aşırı yüke sahibim:

unsigned char*
const char*
unsigned char
const char

Sadece bunların hepsini idare eden bir metoda sahip olmamayı tercih ederim. Ben sadece seri port üzerinden iletmek istediğiniz işlevini çağırdığınızda zorlukla yapmak istemiyorum bu yüzden, çok fazla kaynağınız yok ŞEY benim iletim ama.

Başka biri programımı gördü ve “neden CPP dosyalarını kullanıyorsunuz?” Diye sordu. Demek tek sebebim bu. Bu kötü bir uygulama mı?

Güncelleme

Sorulan bazı soruları ele almak istiyorum:

İkileminize nesnel bir cevap, şunlara bağlı olacaktır:

  1. C ++ kullanıyorsanız, çalıştırılabilir boyutunun önemli ölçüde büyüyüp büyümediği.

Şu an itibariyle, çalıştırılabilir boyutun büyüklüğü program belleğinin% 4.0'ını (5248 bayttan) ve% 8.3'ünü (342 bayttan) tüketmektedir. Yani, C ++ için derleme ... C için nasıl görüneceğini bilmiyorum çünkü C derleyicisini kullanmıyordum. Bu programın artık büyümeyeceğini biliyorum, bu yüzden kaynakları ne kadar sınırlı olduğu için orada iyi olduğumu söyleyebilirim ...

  1. C ++ kullanıyorsanız performans üzerinde gözle görülür bir olumsuz etki olup olmadığı.

Eğer varsa, hiçbir şey fark etmedim ... ama yine de tam olarak anlamadığım için bu soruyu sormamın nedeni bu olabilir.

  1. Kodun yalnızca bir C derleyicisinin bulunduğu farklı bir platformda tekrar kullanılıp kullanılamayacağı.

Bunun cevabının kesinlikle hayır olduğunu biliyorum . Aslında farklı bir işlemciye geçmeyi düşünüyoruz, ancak yalnızca daha güçlü ARM tabanlı işlemciler (bunların hepsinin C ++ derleyici araç zincirleri olduğunu biliyorum).


59
C ++ 'ı sadece //yorum yapabilmem için sadece C özelliklerini kullanan bir proje için kullandım . İşe yararsa, neden olmasın?
Jules

76
Vermediği özellikleri iyi kullandığınızda, kötü uygulama kendinizi C ile sınırlar.
Jerry Coffin

35
"C ++ derleyicisi kullan" derken, "C ++ kullan" deyin. Söyle gitsin. C'yi bir C ++ derleyicisi ile derleyemezsiniz, ancak C'den C ++ 'ya kolayca geçiş yapabilirsiniz , ki bu gerçekten ne yaptığınızdır.
user253751

4
“Yaptığım şey için, işlemci üzerinde dinamik bellek ayırma işlemi yok ve program genel olarak oldukça basit. Cihazın neredeyse işlemci gücü veya kaynağı olmadığından bahsetmiyorum. Herhangi bir C ++ kullanmaya gerçekten gerek yok.” İnşallah bu iki cümlenin ilki C ++ 'ı kullanmama nedenleri olmalı, çünkü eğer oldukça kötü olanlar. C ++, gömülü sistemlerle kullanım için gayet iyi.
Pharap

21
@Jules Bunu bildiğinizden ve bir süre önce tekrar düşündüğünüzden eminim, ancak birilerinin bunu okuması durumunda: //yorumlar C99'dan beri C standardında.
Davislor

Yanıtlar:


77

Başına "kötü uygulama" diyecek kadar ileri gitmezdim , ama bunun da sizin probleminize doğru bir çözüm olduğuna ikna olmadım. İstediğiniz tek şey dört veri türünüzü yapmak için dört ayrı işlevse, neden C programcılarının eskiden beri yaptıklarını yapmayın:

void transmit_uchar_buffer(unsigned char *buffer);
void transmit_char_buffer(char *buffer);
void transmit_uchar(unsigned char c);
void transmit_char(char c);

Bu, C ++ derleyicisinin yine de sahne arkasında yaptığı şeydir ve programcı için bu kadar büyük değildir. "Neden bir C ++ derleyicisi ile oldukça C yazmıyorsunuz?" Sorunlarından kaçınır ve projenizdeki başka hiç kimsenin, C ++ bitlerinin "izin verdiği" ve hangi bitlerin alınmadığıyla karıştırılmayacağı anlamına gelir.


8
Neden olmasın, çünkü iletilmekte olan türün (muhtemelen) bir uygulama ayrıntısı olduğunu, dolayısıyla gizlenmenin ve derleyicinin uygulamanın seçilmesiyle ilgilenmesine izin vermenin daha fazla okunabilir kodla sonuçlanabileceğini söyleyebilirim. C ++ özelliğini kullanmak okunabilirliği arttırırsa, neden bunu yapmıyorsunuz?
Jules

29
Hatta yapabilirsiniz #defineC11 kullanılarak) (iletmek_Generic
Deduplicator

16
@Jules Çünkü projede hangi C ++ özelliklerinin kullanılmasına izin verildiği konusunda kafa karıştırıcı. Nesneleri içeren potansiyel bir değişiklik reddedilir mi? Peki ya şablonlar? C ++ tarzı yorumlar? Elbette, kodlama stili bir belge ile bunun üzerinde çalışabilirsiniz, ancak yaptığınız tek şey basit bir fonksiyon yüklemesi durumuysa, bunun yerine C yazmanız yeterlidir.
Philip Kendall

25
@Phillip "C ++ tarzı yorumlar" bir on yıl boyunca C için geçerli olmuştur.
David Conrad

12
@Jules: iletilmekte olan tür muhtemelen sigorta fiyat teklifi veren yazılımlar için bir uygulama detayı olsa da, OP'ler uygulaması, tür ve veri boyutunun önemli olduğu, seri iletişim kurarken gömülü bir sistem gibi görünmektedir.
whatsisname,

55

C ++ 'ın sadece bazı özelliklerinin kullanılması, aksi halde onu C olarak değerlendirirken, tam olarak yaygın değildir, fakat aynı zamanda her ikisinden de tam olarak haberdar değildir. Aslında, bazı insanlar daha sert ve daha güçlü tip kontrolü dışında, hiçbir C ++ özelliğini kullanmazlar . Sadece C yazarlar (yalnızca C ++ ve C ortak kesişiminde yazmaya dikkat ederler), daha sonra tip kontrolü için bir C ++ derleyicisi ve kod oluşturma için bir C derleyicisi ile derlenirler (ya da sadece C ++ derleyicisine devam ederler).

Linux, insanların düzenli olarak classyeniden adlandırılmasını klassya da yeniden adlandırılmasını ya da kclassLinux'u bir C ++ derleyicisi ile derleyebilmelerini istedikleri bir kod temeli örneğidir . Açıkçası, Linus'un C ++ düşüncesi göz önüne alındığında , her zaman vuruluyorlar: - D GCC, önce "C ++ - temiz C" ye dönüştürülen ve daha sonra C ++ özelliklerini kullanmak üzere yavaş yavaş yeniden düzenlenmiş bir kod temeli örneğidir.

Yaptıklarının yanlış bir şey yok. C ++ derleyicinizin kod oluşturma kalitesi konusunda gerçekten paranoyaksanız, C'yi hedef dili olarak derleyen Comeau C ++ gibi bir derleyici kullanabilir ve ardından C derleyicisini kullanabilirsiniz. Bu şekilde, C ++ kullanmanın öngörülemeyen performansa duyarlı herhangi bir kodu enjekte edip etmediğini görmek için kodun yerinde incelemelerini de yapabilirsiniz. Bu sadece aşırı yükleme için geçerli olmamalı, gerçekte, kelimenin tam anlamıyla sadece otomatik olarak farklı isimlendirilmiş fonksiyonlar üretiyor - IOW, yine de C'de ne yapacağınızı.


15

İkileminize nesnel bir cevap, şunlara bağlı olacaktır:

  1. C ++ kullanıyorsanız, çalıştırılabilir boyutunun önemli ölçüde büyüyüp büyümediği.
  2. C ++ kullanıyorsanız performans üzerinde gözle görülür bir olumsuz etki olup olmadığı.
  3. Kodun yalnızca bir C derleyicisinin bulunduğu farklı bir platformda tekrar kullanılıp kullanılamayacağı.

Sorulardan herhangi birinin cevapları "evet" ise, farklı veri türleri için farklı adlandırılmış işlevler oluşturup C ile yapışmakta daha iyi olabilirsiniz.

Tüm soruların cevapları "hayır" ise, C ++ kullanmamanız için hiçbir neden göremiyorum.


9
İki dilin paylaşılan alt kümesinde yazılan kod için C derleyicisinden önemli ölçüde daha kötü kod üreten bir C ++ derleyicisiyle hiç karşılaşmadım. C ++ derleyicileri hem boyut hem de performans açısından kötü bir temsilci elde ediyor, ancak benim deneyimim, soruna neden olan C ++ özelliklerinin her zaman uygunsuz kullanımı ... Özellikle de, boyuttan endişe ediyorsanız, iostreams kullanmayın ve kullanmayın şablonları, ancak aksi takdirde iyi olmalısınız.
Jules

@Jules: Sadece neye mal olursa olsun (çok fazla değil, IMO) C ve C ++ için tek bir derleyici olarak neyin satıldığını gördüm (bellek kullanılıyorsa Turbo C ++ 1.0) aynı girdi için çok farklı sonuçlar veriyor. Anladığım kadarıyla, bu kendi C ++ derleyicilerini bitirmeden önceydi, bu yüzden dışarıdaki bir derleyici gibi görünse de, gerçekten iki tamamen ayrı derleyiciye sahipti - biri C için diğeri C ++ için.
Jerry Coffin,

1
@JerryCoffin Eğer bellek işe yararsa, Turbo ürünleri hiç bu kadar iyi bir üne sahip olmamıştır. Ve eğer 1.0 versiyonu olsaydı, çok fazla rafine edilmediğiniz için mazeret göreceksiniz. Bu yüzden muhtemelen pek temsili değil.
Barmar

10
@Barmar: Aslında, bir süredir oldukça iyi bir üne sahiplerdi. Şimdiki kötü şöhretleri, esasen onların yaşlarına bağlı. Aynı vintagedeki diğer derleyicilerle rekabet ediyorlar - ancak hiç kimse gcc 1.4 (ya da her neyse) ile işlerin nasıl yapılacağı hakkında soru göndermiyor. Ama haklısın - çok temsili değil.
Jerry Coffin,

1
@Jules Şablonların bile iyi olduğunu iddia ediyorum. Popüler teoriye rağmen, bir şablonun başlatılması kod boyutunu dolaylı olarak artırmaz, kod boyutu genellikle bir şablondan bir işlev kullanılıncaya kadar (bu durumda boyut artışı işlev boyutuyla orantılı olur) veya şablon olmadıkça artar statik değişkenlerin bildirilmesi. Satır içi oluşturma kuralları hala geçerlidir, bu nedenle tüm işlevlerin derleyici tarafından satır içine alındığı şablonları yazmak mümkündür.
Pharap

13

Soruyu C ++ ile derlemeniz size basitçe daha fazla özelliğe erişme imkanı sağladı. Durum bu değil. Bir C ++ derleyicisi ile derlemek, kaynak kodunuzun C ++ kaynağı olarak yorumlanması anlamına gelir ve C ++ C'den farklı bir dil anlamına gelir. Her iki dilde de kabul edilebilir ancak farklı şekilde yorumlanmış kod yazmak mümkündür.

İstediğiniz tek şey gerçekten fonksiyon aşırı yükleme ise, o zaman C ++ 'ı buna sokarak konuyu karıştırmanın nedenini gerçekten anlamadım. Aynı isimdeki farklı fonksiyonlar yerine, parametre listelerini ayırt etmiş, sadece farklı isimler içeren fonksiyonlar yazmalısınız.

Hedef kriterlerinize gelince,

  1. C ++ kullanıyorsanız, çalıştırılabilir boyutunun önemli ölçüde büyüyüp büyümediği.

Yürütülebilir dosya, C ++ ile derlendiğinde, bu şekilde oluşturulan benzer C koduna göre biraz daha büyük olabilir. En azından, C ++ yürütülebilir dosyası, tüm işlev adları için, herhangi bir sembolün yürütülebilir dosyada tutulduğu ölçüde C ++ adının kullanılmasının şüpheli yararına sahip olacaktır. (Ve asıl olarak, aşırı yüklerinizi ilk etapta sağlayan şey budur.) Farkın sizin için önemli olacak kadar büyük olup olmadığı, deneyle belirlemek zorunda kalacağınız bir şeydir.

  1. C ++ kullanıyorsanız performans üzerinde gözle görülür bir olumsuz etki olup olmadığı.

Tanımladığınız kod için varsayımsal bir saf-C analoguna karşı farkedilir bir performans farkı göreceğinden şüpheliyim.

  1. Kodun yalnızca bir C derleyicisinin bulunduğu farklı bir platformda tekrar kullanılıp kullanılamayacağı.

Buna biraz farklı bir ışık atardım: C ++ ile oluşturduğunuz kodu diğer koda bağlamak istiyorsanız , o zaman diğer kodun da C ++ ile yazılmış ve C ++ ile yazılmış olması gerekir. kendi kodunuzda ("C" bağlantısı bildirerek) özel bir hazırlık yapmak için, ayrıca, aşırı yüklenmiş işlevleriniz için hiçbir şekilde yapamayacağınız şeyler. Diğer yandan, eğer kodunuz C olarak yazılmış ve C olarak derlenmişse, diğerleri C ve C ++ modüllerine bağlayabilir. Bu tür bir problem genellikle tabloları çevirerek üstesinden gelinebilir, ancak C ++ 'a gerçekten ihtiyaç duymadığınız için neden böyle bir konuyu ilk başta kabul ediyorsunuz?


4
"Yürütülebilir dosya, herhangi bir sembolün yürütülebilir dosyada kaldığı ölçüde C ++ ... ile derlendiğinde biraz daha büyük olabilir." Yine de dürüst olmak gerekirse, terbiyeli bir optimizasyon aracı zincirinin bu sembolleri "sürüm" yapılarında soymak için bir bağlantı seçeneğine sahip olması gerekir; bu, yalnızca hata ayıklama yapılarını şişirdikleri anlamına gelir. Bunun büyük bir kayıp olduğunu sanmıyorum. Aslında, daha sık bir faydadır.
Cody Gray,

5

Günün geri kalanında C ++ derleyicisini “daha ​​iyi bir C” olarak kullanmak bir kullanım durumu olarak tanıtıldı . Aslında, erken C ++ tam olarak buydu. Temel tasarım prensibi, yalnızca istediğiniz özellikleri kullanabilmeniz ve kullanmadığınız özelliklerin maliyetine maruz kalmamanızdı. Böylece, işlevleri aşırı overloadyükleyebilirsiniz (amacını anahtar kelime ile ilan ederek !) Ve projenizin geri kalanı sadece derlemekle kalmaz, aynı zamanda C derleyicisinden daha kötü bir kod üretmez.

O zamandan beri diller biraz farklılaştı.

Her mallocC kodunuzda bir tür uyuşmazlık hatası olacaktır - sizin durumunuzda dinamik bellek olmayan bir problem değil! Aynı şekilde, voidC'deki tüm işaretçileriniz sizi öne çıkarır, çünkü açık yayınlar eklersiniz. Ama… neden bu şekilde yapıyorsun … C ++ özelliklerini daha fazla kullanma yolunda ilerlemiş olacaksın.

Bu yüzden, bazı ekstra çalışmalarla mümkün olabilir. Ancak daha büyük ölçekli C ++ evlat edinme için bir geçit görevi görecek. Birkaç yıl sonra, 1989’da yazılmış gibi görünen eski kodunuzdan, mallocçağrılarınızı değiştirirken new, eskiden sadece bir algoritma çağırmak için döngü gövdesi kod bloklarını söküp, güvenli olmayan sahte polimorfizmi bozmaktan şikayet edeceklerdir. derleyicinin yapmasına izin verilmiş olması önemsiz olmuştur.

Öte yandan, sen C ile yazmış olsaydın, aynı olacağını biliyorsun, peki varlığından dolayı C ++ yerine C yazmak hiç yanlış mıydı? Cevabınız “hayır” ise, C ++ 'dan kirazlı özellikleri kullanmak da yanlış olamaz .


2

Pek çok programlama dili, çevresinde gelişen bir veya daha fazla kültüre sahiptir ve bir dilin "ne" olması gerektiği hakkında belirli fikirlere sahiptir. Her ne kadar uygun olacak C ++ 'dan bazı özelliklerle bu tür bir amaç için uygun bir C lehçesini güçlendiren sistem programlaması için uygun düşük seviyeli bir dilin olması mümkün, pratik ve kullanışlı olsa da, iki dili çevreleyen kültürler özellikle böyle bir birleşme lehine.

Sahip olma yeteneği de dahil olmak üzere C ++ 'dan bazı özellikleri içeren gömülü bir C derleyicisini okudum.

foo.someFunction(a,b,c);

aslında olarak yorumlanır

typeOfFoo_someFunction(foo, a, b, c);

statik işlevleri aşırı yükleme yeteneğinin yanı sıra (isim yönetimi sorunları yalnızca dışa aktarıldığında ortaya çıkar)fonksiyonlar aşırı yüklenmiştir). C derleyicilerinin böyle bir işlevselliği, bağlantı ve çalışma zamanı ortamı için herhangi bir ek gereksinim getirmeden destekleyememelerinin bir nedeni yoktur, ancak birçok C derleyicisi çevresel yüklerden kaçınmak amacıyla C ++ 'dan hemen hemen her şeyin geri dönüşü reddetmesine neden olur. Böyle bir maliyet getirmeyen özellikleri bile reddeder. Bu arada, C ++ kültürü, o dilin tüm özelliklerini destekleyemeyen herhangi bir çevreye çok az ilgi duyuyor. C kültürü bu özellikleri kabul etmek için değişmediği sürece veya C ++ kültürü hafif altkümelerin uygulamalarını teşvik edecek şekilde değişmedikçe, "karma" kod, her iki dilin sınırlamalarının çoğundan muzdarip olma özelliğini korurken kombine bir süpermarkette çalışmanın faydaları.

Eğer bir platform hem C hem de C ++ 'ı destekliyorsa, C ++' ı desteklemek için gereken ekstra kütüphane kodu muhtemelen etkileyici olmakla birlikte büyük oranda çalıştırılabilir hale getirecektir. C ++ 'da "C özelliklerinin" yürütülmesi büyük olasılıkla özellikle etkilenmeyecektir. Daha büyük bir sorun, C ve C ++ iyileştiricilerin çeşitli köşe kasalarını nasıl ele aldıkları olabilir. Bir C'deki veri tiplerinin davranışı çoğunlukla burada depolanan bitlerin içeriği ile tanımlanır ve C ++, semantiği de çoğunlukla depolanan bitler tarafından tanımlanan tanınmış bir yapı kategorisine (PODS - Düz Eski Veri Yapıları) sahiptir. Bununla birlikte, hem C hem de C ++ standartları bazen depolanan bitlerin ima ettiği davranışa izin verir ve "depolanan bit" davranışının istisnaları iki dil arasında farklılık gösterir.


1
İlginç görüş, ancak OP'nin sorusunu ele almıyor.
R Sahu

@ RSahu: Bir dili çevreleyen "kültüre" uyan kod, desteklenmeyen kodlara göre daha iyi desteklenmeye ve çeşitli uygulamalara daha kolay adapte olmaya uygundur. C ve C ++ kültürlerinin her ikisi de OP'nin önerdiği kullanım biçimine ters düşüyor, belirli sorulara ilişkin daha spesifik noktalar ekleyeceğim.
supercat

1
C ++ standart komitesinde, atıldığını iddia ettiğiniz "küçük ilgi" durumlarını tam olarak çözmeyi amaçlayan bir gömülü / finansal / oyun grubunun bulunduğunu unutmayın.
Yakk

@Yakk: C ++ dünyasını çok yakından takip etmediğimi itiraf edeceğim, çünkü çıkarlarım çoğunlukla C ile yatıyor; Daha fazla gömülü lehçeye yönelik çabalar olduğunu biliyorum, ama gerçekten bir yere varacaklarını düşünmemiştim.
supercat

2

Dikkate alınması gereken bir diğer önemli faktör: kodunuzu kim devralacaksa.

Bu kişi her zaman C derleyicili bir C programcısı olacak mı? Bende öyle tahmin ediyorum.

Bu kişi aynı zamanda bir C ++ derleyicisine sahip bir C ++ programcısı olacak mı? Kodumu C ++ 'ya özgü şeylere bağlı kılmadan önce bu konuda oldukça emin olmak isterdim.


2

Polimorfizm, C ++ 'ın ücretsiz sağladığı gerçekten iyi bir özelliktir. Bununla birlikte, bir derleyici seçerken göz önünde bulundurmanız gereken başka hususlar da vardır. C de polimorfizmin bir alternatifi var, ancak kullanımı kaşların yükselmesine neden olabilir. Değişken işlev, lütfen Değişken işlevi öğreticisine bakın .

Senin durumunda böyle bir şey olurdu

enum serialDataTypes
{
 INT =0,
 INT_P =1,
 ....
 }Arg_type_t;
....
....
void transmit(Arg_type_t serial_data_type, ...)
{
  va_list args;
  va_start(args, serial_data_type);

  switch(serial_data_type)
  {
    case INT: 
    //Send integer
    break;

    case INT_P:
    //Send data at integer pointer
    break;
    ...
   }
 va_end(args);
}

Phillips'in yaklaşımını seviyorum ama çok fazla çağrı ile kütüphanenizi aydınlatıyor. Yukarıdakilerle arayüz temizdir. Onun sakıncaları var ve nihayetinde bir seçim meselesi.


Değişkin fonksiyonlar öncelikle argüman sayısı hem kullanım örneğini hizmet ve onların türleri değişkendir. Aksi takdirde, ihtiyacınız yoktur ve özellikle, sizin özel örneğiniz için fazla önemlidir. Verileri kabul eden Arg_type_tve void *işaret eden normal bir fonksiyon kullanmak daha kolay olacaktır . Bununla birlikte, evet, (tek) işlevine, veri türünün gerçekten geçerli bir alternatif olduğunu belirten bir argüman verilmesi.
John Bollinger

1

Bir kaç farklı tip için statik olarak bir "fonksiyon" a aşırı yükleme durumunuz için, bunun yerine sadece _Genericmakro makinelerinde C11'i kullanmayı düşünebilirsiniz . Sınırlı ihtiyaçlarınız için yeterli olabileceğini düşünüyorum.

Philip Kendall'ın cevabını kullanarak şunları tanımlayabilirsiniz:

#define transmit(X) _Generic((X),      \
   unsigned char*: transmit_uchar_buffer, \
   char*: transmit_char_buffer,           \
   unsigned char: transmit_uchar,         \
   char: transmit_char) ((X))

ve transmit(foo) türünü ne olursa olsun kodlayın foo(yukarıda listelenen dört tür arasında).

Yalnızca GCC (ve uyumlu, örneğin Clang ) derleyicileriyle __builtin_types_compatible_pilgileniyorsanız, typeofuzantısını bunun bir parçası olarak düşünebilirsiniz .


1

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 memsetve günlük olmayan fonksiyonlar olan günlük fonksiyonlar memcpyher 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:

memcpyve memcmptip sistemini ihlal eder. Kullanılması memcpynesneleri kopyalamak için bir fotokopi kullanarak para kazanma gibidir. Kullanma memcmpnesneleri 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 memcpyciddi 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 memcpytü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, mallocbir 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. freeBu 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 .cppuzantısı ya da her neyse ve benzeri şeylerin hepsini bu tür yapar malloc, memcpy, memset,qsortvb., 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,728C 9,278olarak 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.

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.