C neden 'nesne yönelimli' bir dil olarak kabul edilmiyor?


92

C'nin, nesneler olarak kabul edilebilecek (normal olarak düşüneceğimiz en üst düzeyde) nesneler olduğu gibi “yapılar” gibi kendi yarı-nesneleri vardır.

Ve ayrıca, C dosyaları kendileri temelde ayrı "modüller" dir, değil mi? Öyleyse modüller de 'nesneler' gibi değil mi? Neden C ++ 'a çok benzeyen C' nin düşük seviyede "usule dayalı" bir dil olarak kabul edildiğine dair kafam karıştı.

* edit: (açıklama) neden bir 'nesne' olduğu ve neden olmadığı için çizgi çizilir ve nerede?


40
Hepsi - neden aşağı oy? Bu temel bir soru ama kötü bir soru değil.
Jon Hopkins

7
OO ilkelerini C'de etkili bir şekilde kullanabilirsiniz (ve genellikle iyi C kodu yazan insanlar da yapar), ancak dil, daha birçok dilde olduğu gibi, onu kolaylaştıracak şekilde oluşturulmamıştır.
asveikau

5
C, veri soyutlamaya daha iyi tanımlanmış (en azından açık kaynaklı topluluklar arasında ) daha farklı, daha basit ve (dürüst olmak gerekirse ) bir yaklaşıma sahiptir. C ++ bir soyutlama güç merkezi olma eğilimindedir ve birçok harika şeye izin verir, ancak bunları ortak programlarda oldukça eksik olan, onları doğru şekilde kullanmamaya [anlama] anlamında bir bedelle gelir. Daha fazla ayrıntı için tam cevabımı görün.
Yam Marcoviç

1
Kısaca: Yapıların metodu olamaz. (Bir işleve işaretçi tam olarak kesmiyor).
SF.

1
Nesneye dayalı programlama C dilinde biraz zorlukla yapılabilir. Fakat bu onu nesne yönelimli yapmaz .
Kama

Yanıtlar:


101

C'nin nesne olarak kabul edilebilecek 'yapılar' gibi kendi yarı-nesnelerine sahip olduğu görülüyor.

Siz ve ben bir araya gelip , Wikipedia sayfasını nesne yönelimli programlama hakkında okuduk ve geleneksel olarak nesne yönelimli stil olarak kabul edilen C-tarzı yapıların özelliklerini gözden geçirelim :

(OOP) "nesneler" kullanan bir programlama paradigmasıdır - etkileşimlerle birlikte veri alanlarından ve yöntemlerden oluşan veri yapıları.

C yapıları etkileşimleriyle birlikte alanlardan ve yöntemlerden oluşuyor mu? Hayır.

Programlama teknikleri, veri soyutlama, kapsülleme, mesajlaşma, modülerlik, polimorfizm ve kalıtım gibi özellikleri içerebilir.

C yapıları bunlardan herhangi birini "birinci sınıf" şekilde yapıyor mu? Hayır. Dil, yolun her adımında size karşı çalışır.

Nesne yönelimli yaklaşım, programcının veriyi programın geri kalanı tarafından doğrudan erişilemeyen yerlere yerleştirmesini teşvik eder.

C yapıları bunu yapar mı? Hayır.

Bir nesneye yönelik program genellikle farklı nesneler içerecektir; her biri, yönetilmesi gereken belirli bir karmaşık verilere veya belki de gerçek dünyadaki bir nesneye veya konsepte karşılık gelen

C yapıları bunu yapar mı? Evet.

Nesneler, verilerin uygun şekilde kullanılmasını sağlamak için tasarlanmış bir dizi fonksiyonun içine verileri sardığı şeklinde düşünülebilir.

Hayır.

her nesne mesaj alma, veri işleme ve diğer nesnelere mesaj gönderme yeteneğine sahiptir.

Bir yapının kendisi mesaj gönderip alabilir mi? Hayır. Verileri işleyebilir mi? Hayır.

OOP veri yapıları "kendi operatörlerini yanlarında taşıma" eğilimindedir

Bu C de olur mu? Hayır.

Dinamik gönderi ... Kapsülleme ... Türü polimorfizmi ... Nesne mirası ... Açık özyineleme ... Nesne sınıfları ... Sınıf örnekleri ... Ekli nesneler üzerinde etki eden yöntemler ... Mesaj iletme .. Soyutlama

C yapılarının bu özelliklerinden herhangi biri var mı? Hayır.

Yapıların tam olarak hangi özelliklerinin "nesne yönelimli" olduğunu düşünüyorsunuz? Bulamıyorum Çünkü herhangi yapılar tanımlamak olması dışında türleri .

Şimdi, elbette fonksiyonlara işaret eden alanları olan yapılar yapabilirsiniz. Yapıların, sanal yöntem tablolarına karşılık gelen, işlev işaretçilerinin dizileri için işaretçiler olan alanları oluşturabilirsiniz. Ve bunun gibi. Tabii ki C ++ 'ı C cinsinden taklit edebilirsiniz. Ancak bu, C de programlamanın çok aptalca bir yolu değildir; Sadece C ++ kullanarak daha iyi olurdun.

Ve ayrıca, C dosyaları kendileri temelde ayrı "modüller" dir, değil mi? Öyleyse modüller de 'nesneler' gibi değil mi?

Yine, modüllerin hangi özelliklerinin nesneler gibi hareket etmelerini sağladığını düşünüyorsunuz? Modüller soyutlamayı, kapsülleme, mesajlaşmayı, modülerliği, polimorfizmi ve mirası destekliyor mu?

Soyutlama ve kapsülleme oldukça zayıf. Açıkçası modüller modüler; Bu yüzden onlara modül denir. Mesajlaşma? Sadece bir yöntem çağrısının bir mesaj olduğu ve modüller anlamında yöntemler içerebilir. Polimorfizm? Hayır! Kalıtım? Hayır! Modüller "nesneler" için oldukça zayıf adaylardır.


15
"C ++ öykünmesi" nin (deyiminiz) deyimsel C olmadığı konusunda hemfikir değilim. Bir karşı örnek, bir işletim sistemi çekirdeğinin tipik olarak dosya işlemlerini gerçekleştirme şekli olabilir - Linux'u işlev göstergeleriyle dolu yapılara sahip olduğunuz bir örnek olarak alır. Biraz "etki alanına özgü" deyimler olabilir (* nix üzerine sürücü yazmakla sınırlıdır), ancak tanınabilirler ve işi bazı amaçlar için yeterince temiz yaparlar. Bazı OO kavramlarını yeterince iyi yapan bazı kullanıcı modu kitaplıkları örnekleri de vardır; Gtk + 'ı ve bağlı olduğu kütüphaneleri alın. Hacky deyin ve doğru olabilir, ancak bunlar ile çalışmak korkunç değildir
asveikau

5
@ asveikau: Bir uygulamanın alışılmadık olduğu (duyulmamış olsa bile) ve "hack" olduğu iddiası anlamıyla aptalca olmadığı anlamına gelmiyor mu?
Adam Robinson

19
@ asveikau: Elbette, C programlarını tarzında daha fazla OO yapmak için yapabileceğiniz şeyler var. Ancak dediğiniz gibi, disiplini gerektirir; Dil özellikleri, doğal olarak sizi kapsülleme, polimorfizm, sınıf mirası vb. yollarda yönlendirmez. Aksine, geliştirici bu kalıbı dile uygulayabilir. Bu, yapıların mantıksal olarak nesnelerle aynı şey olduğu anlamına gelmez. Heck, Lisp'te OO tarzında da programlayabilirsiniz, ancak bu, eksilerin hücrelerinin nesne olduğu anlamına gelmez.
Eric Lippert 11:11

3
@ asveikau, "deyim" in ("yanlış") "deyimin" "kendi" olarak yorumlanmasının hafifçe ... kendi kendine özgü olduğunu önerebilir miyim? :)
Benjol

8
@BillK: Yapılar C kodunu içeremez. Yapılar veri olan işlev işaretleyicileri içerebilir . İşlev işaretçileri kod değildir . Kod , bir programcı tarafından oluşturulan bir metinsel yapıdır.
Eric Lippert

46

Anahtar kelime "nesne" değil "yönelimli" dir. Nesneleri kullanan ancak bunları yapılar gibi kullanan C ++ kodu bile nesneye yönelik değildir .

C ve C ++ her ikisi de OOP yapabilir (C'de erişim kontrolü olmaması dışında), ancak C'de yapmak için sözdizimi sakıncalıdır (en azından söylemek gerekirse), C ++ sözdizimi bunu çok çekici kılar. C yordamsal odaklı iken, C ++ bu konudaki özdeş yeteneklere rağmen nesnelere yöneliktir.

Sadece nesnelerle yapılabilecek (genellikle polimorfizmden faydalanmak anlamına gelir) tasarımları uygulamak için nesneleri kullanan kod nesneye yönelik koddur. Nesneleri veri paketlerinden çok daha az kullanan, hatta nesne yönelimli bir dilde kalıtım bile kullanan kod, olması gerekenden daha karmaşık olan prosedürsel bir koddur. Çalışma zamanında veri dolu yapılarla değiştirilen fonksiyon işaretleyicilerini kullanan C kodunda, polimorfizm yapılıyor ve usule yönelik bir dilde bile "nesne yönelimli" olduğu söylenebilir.


2
+1 C'yi işaret etmek için OO olabilir. Uygun değil, ama yapılabilir.
dietbuddha

VBA'da nesne oluşturmak daha kolay, ancak nesneyi de 'yönlendirilmiş' olarak düşünmüyorum.
JeffO

VBA "nesne tabanlı" diyorum. Nesneleri kullanır, ancak polimorfik olarak kullanmaz, ve içinde yaptığım az miktarda çalışmayla, ne tür kod akrobasi denerseniz, polimorfizmi bile yapabileceğinizden emin değilim. Temelde kapsülleme ile bir prosedür dili.
kylben

2
Çoğu dil, OO, fonksiyonel veya hemen hemen her dil tarzı olarak işlev görebilir. Aradaki fark “Odaklı” dır ve daha önce bu şekilde koyduğunu duymadım. Keşke bunu 3 kez oylayıp kabul edebilseydim, doğru cevap.
Bill K,

1
@kylben SQL kodunu tabloda depolamak, sonra çıkarmak ve çalıştırmak (tabloyu nesneniz yapmak) çok zor olmazdı. İlginç bir deney olurdu. Aslında biraz baştan çıkarıcı ...
Bill K

19

En üst düzey müdürlere göre:

Bir nesne, dış arayüzü biliyorsanız, bir defalarca başlatılabilen ve kara bir kutu üzerinde çalışılabilecek bir bütün olarak çalışacak şekilde, veri ve davranışın birbirine bağlı bir şekilde kapsüllenmesidir.

Yapılar veri içerir ancak davranış içermez ve bu nedenle nesneler olarak kabul edilemez.

Modüller hem davranış hem de veri içerir, ancak ikisinin ilişkili olduğu ve kesinlikle birden fazla kez başlatılamayacağı şekilde kapsüllenmez.

Ve bu, miras ve polimorfizme girmeden önce ...


Modüllerdeki davranış ve veri nasıl ilişkili değildir? Üye temelde modülün içinde yer alan verilerdeki 'davranış' değil midir?
Karanlık Tapınak

4
Sorun, kapsüllenmemiş olmaları, ilişkili olmadıklarıdır.
Eoin Carroll

Aslında nesneler temelde davranış yerine verilere odaklanır . Veriler OOP'ta ikinci sınıf bir vatandaşdır / olmalıdır. Yapılar, bunun yerine verilerin etrafında toplanır ve davranışları yoktur.
Sklivvz

1
@Dark Templar - Eoin ne dedi ... İlişkinin doğasında var. Nereden geldiğini görebiliyorum - bir modül içindeki Structs'ı OO'nun bazı çok temel öğelerini taklit edecek şekilde kullanabilirsiniz, ancak yaptığınız işlerin çoğu programlayıcıya bağlı kalır. dilin uygulamasından ziyade kendine empoze edilmiş kurallar. Ve neden rahatsız ediyorsun? OO'nun yararlarından hiçbirini alamıyorsunuz - örneğin miras yok - ve kendinizi kısıtlıyorsunuz.
Jon Hopkins

Bu, doğru olarak işaretlenenden daha iyi bir cevaptır.
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

6

"yapılar" yalnızca veridir. Her zaman "nesne yönelimi" nin hızlı ve kirli testi: "Kod ve verilerin tek bir birim olarak kapsanmasına izin veren bir yapı var mı?" C başarısız olur ve bu nedenle prosedürdür. C ++ bu testi geçiyor.


6
Geçici çözümler vardır, yapıların üye işlevlerine statik işlev göstergeleri olabilir. Açık bir şekilde işaretleyiciye ihtiyaç duyacaklar this, ancak bu durumda, verileri işlemek için veri ve araçlar yapı içinde kapsüllenecektir.
Kodlayıcı

@Brian Knoblauch: ama bir C dosyasının kendisi veri ve kodun içine alınmıyor mu ??
Karanlık Tapınak

@DarkTemplar Bir anlamda, evet, ancak çeviri birimleri oluşturmayı başaramazsanız, bunları derleyin ve çalışma süresinde bunları çalışma sürecine yükleyin.

çeviri birimleri? >. <
Karanlık Tapınak

@Dark Templar: Bir çeviri ünitesi, bir kaynak dosya artı bir şey #includekoşullu eklenmesini içine d ve eksi değil uzaklaştırıldı herhangi bir şey ( #if, #ifdefve benzeri).
David Thornley

5

C, tıpkı C ++ gibi, kendisinden önce var olan nesne yönelimli programlama paradigmasının bir deyimi olan Veri Soyutlama özelliğini sağlama kabiliyetine sahiptir .

  • C yapılarının verileri olabilir (ve bu onların temel amacı)
  • C yapıları ayrıca fonksiyon işaretleyicilerini veri olarak tanımlayabilir.
  • C yapıları, çoğu yöntemde olduğu gibi bunlarla ilişkili bir dizi işlevi de içerebilir ve sık sık kullanır; yalnızca bu işaretçi dolaylı olarak iletilmez, ancak açıkça belirtilen yapıyı işlemek için tasarlanan her yöntemin ilk argümanı olarak belirtmeniz gerekir. C ++ bunu hem sizin hem de class / struct yöntemlerini tanımladığınızda ve çağırdığınızda otomatik olarak yapar .

C ++ 'daki OOP veriyi soyutlama yolunu genişletir Bazıları zararlı olduğunu söylerken, bazıları doğru kullanıldığında iyi bir araç olduğunu düşünüyor.

  • C ++, bu işaretleyiciyi , tür tanımlandığı sürece (en azından kısmen) kullanıcının "sınıf / yapı yöntemlerine" geçirmesini gerektirmeyerek örtük yapar .
  • C ++, belirli yöntemlere (sınıf işlevleri) erişimi kısıtlamanıza izin verir ve bu nedenle daha fazla "savunma programlaması" veya "salak prova" için izin verir.
  • C ++, daha güçlü tip güvenliği sağlayarak soyutlamaları teşvik eder.
    1. Yeni yerine operatör malloc + döküm
    2. Boşluk işaretçiler yerine şablonlar
    3. Satır içi işlevler makro yerine yazılan değerler alıyor
    4. Kendinizi uygulamak zorunda olmadığınız, soyutlama hiyerarşileri , sözleşmeler ve uzmanlıklar yaratmanıza izin veren Polimorfizm üzerine inşa edilmiştir .

Bununla birlikte, C'nin sadece doğru miktarda soyutlama yapabildiğini ve C ++ 'nın yarattığı ek yükün onları asıl sorunu çözmekten nasıl uzaklaştıracağı konusunda vaaz veren birçok C "korsanını" bulacaksınız.

Yola iki yıl boyunca bazı soyutlamaların çok verimli olmadığını fark ettiğiniz, verimsiz soyutlanmış programlama modelleri, ancak şimdi tüm kodunuz etrafındaki tüm güzel nesne modellerine bağlıdır ve uygulamanızı yeniden yazmadan düzeltemezsiniz. - Linus Torvalds

Diğerleri dezavantajların yanı sıra her iki avantajı da kabul ederek daha dengeli bir şekilde bakma eğilimindedir.

C kendini ayağından vurmayı kolaylaştırır; C ++ zorlaştırıyor, ancak bunu yaptığınızda bütün bacağınızı uçuruyor. - Bjarne Stroustrup


2

Madalyonun diğer tarafına bakmanız gerekir: C ++.

OOP'ta soyut bir nesne (ve programı buna göre tasarlar), örneğin durdurabilen, hızlandırabilen, sola veya sağa çevirebilen bir otomobil vb. Düşünürüz.

Örneğin "gerçek" nesnelerle, üyeleri gizlememiz gerekir, ya da gerçek bir mirasa sahip olabiliriz "bir" ilişkidir ve daha birçok şey.

AŞAĞIDAKİ YORUMLARI OKUMADAN SONRA: Eh (hemen hemen) her şeyin C ile yapılabileceği doğru (her zaman doğrudur), ancak ilk bakışta c'yi c ++ 'dan ayıran şeyin bir program tasarlarken düşündüğünüz gibi olduğunu düşündüm.

Gerçekten fark yaratan tek şey, derleyici tarafından politikaların empoze edilmesidir . yani saf sanal fonksiyon ve benzeri. ancak bu cevap sadece teknik meselelerle ilgili olacaktır, fakat temel farkın (belirtildiği gibi) kodlama yaparken düşündüğünüz orijinal yol olduğunu düşünüyorum, çünkü C ++ size böyle şeyler yapmak için sözdiziminde daha iyi bir yapıya sahiptir; C. biraz sakarca bir şekilde


Bir "fonksiyon paketi" olan bir yapının neden konsepte uygun olmadığından emin değil misiniz? Cevap için + 1
Karanlık Tapınak

1
Erişim kontrolü dışında (özel / korumalı / kamu) başka her şey yapılarla yapılabilir.
Coder

1
@DarkTemplar: Eh, olabilir sen Java fonksiyonel programlama taklit deneyebilirsiniz gibi (insanlar aslında bu konu üzerinde ebooks yazdım ve çok nadiren de olsa, gerçek dünyada) C OOP taklit deneyin. Fakat C bunun için sıfır yardım sağlar, bu nedenle C dili nesne yönelimli değildir .

1

Kendin söyledin. C, bir nevi benzeri nesnelere sahip olsa da, hala nesneler değildir ve bu nedenle C'nin bir OOP dili olarak kabul edilmemesidir.


1
Şey, sanırım soru şudur: Nesne olan ve olmayan olan için neden ve nerede çizilen çizgi?
Karanlık Tapınak

1

Nesneye Yönelik, hem mimari bir desene (hatta bir meta-desene) hem de bu desenin kullanılmasına veya uygulanmasına yardımcı olacak özelliklere sahip dilleri ifade eder.

Bir "OO" tasarımı uygulayabilirsiniz (Gnome masaüstü belki de saf C'de yapılan en iyi OO örneğidir), bunu COBOL ile bile yaptım!

Bununla birlikte, bir OO tasarım dozunu uygulayabilmek, dili OO yapmaz. Purists, Java ve C ++ 'ın "O" olmadığını, "int" ve "char" gibi temel "türleri" geçersiz kılmayacağınız veya devralamayacağınız ve Java'nın çoklu mirası desteklemediğini iddia edecektir. Ancak en yaygın kullanılan OO dilleri oldukları ve çalışma kodunu üretmek için para alan paradigmanın çoğu "gerçek" programcılarını destekledikleri için onları OO dilleri olarak kabul ederler.

Öte yandan, C sadece (örneğin COBOL, Pascal ve diğer düzinelerce prosedürel dil yapıları gibi) yapıları desteklemektedir, herhangi bir veri parçası üzerinde herhangi bir işlevi kullanabilmeniz için çoklu kalıtımın desteklendiğini ancak bunun bir hata olarak kabul edeceğini iddia edebilirsiniz. bir özellikten daha.


0

OO'nun tanımına bakalım:

  • Mesajlaşma
  • kapsülleme
  • Geç bağlama

C bu üçünden hiçbirini sağlamıyor. Özellikle, en önemlisi olan Messaging'i sağlamaz .


1
Sanırım buna katılmam gerek. Kesinlikle C ile mesajlaşabilirsiniz - C'nin Objective C API'leri ile çalışın ve bunu daha derinlemesine anlayın - ve geç bağlama fonksiyon işaretleyicileri ile yapılabiliyor, ancak gizlemek için çok sözdizimsel şeker almıyorsunuz. (C içinde kapsülleme aslında kolaydır; eksik yapı tiplerini gösteren işaretçiler işi mükemmel yaparlar.)
Donal Fellows

Kalıtım da OO'da önemli olarak kabul edilir ve C bunu yapmaz. C içinde enkapsülasyona en yakın şey internal ( static) fonksiyonlarına ve veri üyelerine sahip olabilecek ayrı dosyalardır .
David Thornley

@DonalFellows, Objective-C'den geçen asıl mesaj bir C99 makrosu olarak kolayca uygulanabilir. Derleyicinin bunun için tek işi, gerekli tüm yapıları statik olarak birkaç yüksek seviye kod satırından üretmesidir. Çoğu özellik C API'sinde mevcut değilse.
qpr

0

OO için çok sayıda anahtar bileşen vardır, ancak büyük olanlar, kodun çoğunluğunun bir nesnenin içinde ne olduğunu bilmediği (uygulamanın değil yüzey arayüzünü gördükleri), bir nesnenin durumunun yönetilen bir birim olduğunu bilmesidir. (yani, nesne durduğunda, durumu da böyledir) ve bazı kodlar bir nesne üzerinde bir işlem başlattığında, o işlemin ne olduğunu veya içerdiğini tam olarak bilmeden bunu yaparlar (tek yaptıkları atmak için bir kalıp izlemektir Duvarın üzerinden “mesaj”).

C kapsülleme gayet iyi; bir yapının tanımını görmeyen kod, (yasal olarak) içerisine bakamaz. Tek yapmanız gereken, böyle bir tanımını bir başlık dosyasına koymaktır:

struct FooImpl;
typedef struct FooImpl *Foo;

Tabii ki, Foos'yi (yani bir fabrika) inşa eden ve işin bir kısmını tahsis edilen nesnenin kendisine (yani bir “kurucu” yöntemiyle) devretmesi gereken bir işleve ihtiyaç duyulacak ve ayrıca bir yolun olması gerekecek. nesneyi tekrar elden çıkarma (“yıkıcı” yöntemiyle temizlenmesine izin verirken) ancak bu ayrıntı.

Metot gönderme (yani mesajlaşma), yapının ilk elemanının aslında fonksiyon işaretçilerle dolu bir yapıya bir işaretçi olduğu ve bu fonksiyon işaretçilerinin her birinin Fooilk argümanını alması gerektiği sözleşmesi yoluyla da yapılabilir . Daha sonra gönderme, işleve bakmak ve onu yeniden yazmak için doğru bir argüman olarak çağırmaktan ibarettir, bu da bir makro ve biraz kurnazlık yapmak zor değildir . (Bu işlev tablosu, bir sınıfın C ++ gibi bir dilde gerçekte ne olduğunun özüdür.)

Dahası, bu size geç bağlanma da sağlar: tüm gönderme kodu, nesnenin işaret ettiği bir tabloya belirli bir ofset çağırdığını biliyor. Bunun yalnızca nesnenin tahsisi ve başlatılması sırasında ayarlanması gerekir. Size daha fazla çalışma zamanı dinamizmi (daha düşük bir maliyetle) satın alan daha karmaşık sevk şemaları ile gitmek mümkündür, ancak bunlar temel mekanizmanın üstünde kirazlar.

Ancak bu, C'nin bir OO dili olduğu anlamına gelmez. Anahtar, C'nin sözleşmeleri yazma ve gönderim mekanizmasını kendinizin zor işlerini yapmanıza (veya bir üçüncü taraf kütüphanesi kullanmanıza) bırakmasıdır. Çok fazla iş var. Aynı zamanda sözdizimsel ya da anlamsal destek sağlamaz, bu yüzden tam sınıf bir sistemi (kalıtım gibi şeylerle) uygulamak gereksiz yere acı verici olacaktır; Bir OO modeli tarafından iyi tanımlanmış karmaşık bir problemle uğraşıyorsanız, bir OO dili çözümü yazarken çok faydalı olacaktır. Ekstra karmaşıklık haklı gösterilebilir.


0

C'nin nesne yönelimli konseptler, omuz silkme uygulamaları için mükemmel derecede iyi ve uygun olduğunu düşünüyorum . Nesneye yönelik olarak kabul edilen dillerin ortak payda altkümesi arasında gördüğüm farkların çoğu, benim pragmatik bakış açımdan doğada küçük ve sözdizimseldir.

Bilgi gizleme ile başlayalım. C'de basitçe bir yapının tanımını gizleyerek ve onunla opak işaretçilerle çalışarak başarabiliriz. Bu , sınıflarla elde ettiğimiz veri alanlarının publicvs. privatefarkını etkili bir şekilde modellemektedir . Standart C kütüphanesi bilgiyi gizlemek için buna çok güvendiği için bunu yapmak yeterince kolaydır ve neredeyse anti-idiomatik değildir.

Elbette, yapının bellekte nereye yerleştirildiğini tam olarak opak tipler kullanarak kolayca kontrol etme yeteneğini kaybedersiniz, ancak bu sadece C ve C ++ arasındaki dikkate değer bir farktır. C ++, bellek düzenleri üzerinde kontrolü sürdürürken, nesne yönelimli kavramları C üzerinden programlama yeteneğini karşılaştırırken kesinlikle üstün bir araçtır, ancak bu, Java ya da C # 'nın C konusunda üstün olduğu anlamına gelmez; bellekte nereye yerleştirildiğini kontrol etme yeteneğini tamamen kaybeder.

Ve büyük boğmaca fopen(file, ...); fclose(file);aksine bir sözdizimi kullanmak zorundayız file.open(...); file.close();. Kim gerçekten önemsiyor? Belki de IDE'lerinde otomatik tamamlama konusunda yoğun bir şekilde dayanan biri. Bunun pratik açıdan çok yararlı bir özellik olabileceğini kabul ediyorum, ancak bir dilin OOP için uygun olup olmadığına dair bir tartışma gerektiren bir konu değil.

protectedAlanları etkin biçimde uygulama yeteneğinden yoksunuz . Ben tamamen oraya gönderirim. Ancak, " Tüm OO dillerinin, alt sınıfların normal müşteriler tarafından hala erişilmemesi gereken bir temel sınıf üyelerine erişmesine izin verme özelliğine sahip olması gerektiğini " söyleyen somut bir kural olduğunu sanmıyorum . Ayrıca en azından biraz bakım engelli olma şüphesi olmayan korunan üyelerin kullanım durumlarını nadiren görüyorum.

Ve elbette, OO polimorfizmini, fonksiyon işaretçilerinin ve işaretçilerinin tablolarıyla "taklit" etmeliyiz, bu analogları başlatmak için biraz daha fazla kazan ile dinamik gönderim için vtablesve vptrsbiraz da kazan plakası bana çok fazla acı vermedi.

Kalıtım aynı şekildedir. Bunu kompozisyon aracılığıyla ve derleyicilerin iç çalışmalarında aynı şeye indirgendiğini kolayca modelleyebiliriz. İstersek Elbette tür güvenliği kaybedersiniz downcast ve olmak istiyorsanız orada söyleyebilirim downcasting insanlar C yapılacak şeyler taklit çünkü bunun için C kullanın lütfen şunu üzere, tüm downcasting bir türünden korkunç olabilir Güvenlik açısından, ama insanların alçalmamasını tercih ederim . Tip güvenliği, derleyicide derleme zamanında oluşabilecek hatalardan ödün vermeden fedakarlıkta bulunma, derleme zamanında meydana gelebilecek hatalardan fedakarlıkta bulunma, ancak bazı diller nesne yönelimli olarak kabul edilir. Hatta statik olarak yazılmış bile değil.

Dunno, bence sorun değil. Tabii ki C'yi SOLID ilkelerine uygun büyük ölçekli bir kod temeli oluşturmaya çalışmak istemem ama bunun nesne yönelimli cephedeki kısa gelişmeleri nedeniyle olması gerekmez. C'yi böyle bir amaç için kullanmaya kalkıştığımda özleyeceğim özelliklerin çoğu, güçlü tip güvenliği, nesneler kapsam dışına çıktığında otomatik olarak çağrılan yıkıcılar gibi doğrudan OOP için ön koşul olarak kabul edilmeyen dil özellikleri ile ilgilidir. aşırı yükleme, şablonlar / jenerik ve istisna işleme. C ++ 'a ulaştığım bu yardımcı özellikleri kaçırdığımda.


1
Yapıcıların OOP için ön koşul olarak nasıl değerlendirilemediğinden emin değilim. Kapsüllemenin temel özünün bir kısmı, bir nesne için değişmezleri sağlama yeteneğidir. Ve bu, değişmeyenlerin içindeki nesneyi uygun şekilde başlatabilmek gerektirir. Bu bir yapıcı gerektirir: bir veya daha fazla işlev, öyle ki nesnenin henüz en az biri çağrılana kadar var olduğunu söyleyemezsiniz.
Nicol Bolas,

Opak tiplerle gizleme bilgisine sahip olduğumuzda, onları başlatmanın ve kopyala / klonlayıp imha etmenin tek yolu, bu değişmezleri koruyabilen kadar yapıcı ve yıkıcı olarak görev yapan fonksiyonların analog eşdeğerinden geçer. Bu sadece doğrudan dile modellenmiş değil ve şeklini andıran olabilir foo_createve foo_destroyve foo_clone, örneğin

Bu struct Foodurumda değişmezleri korumamız gereken tek şey, veri üyelerine dış dünya tarafından erişilemediğinden ve mutasyona uğramayacağından emin olmaktır; bu sayede opak tipler (ilan edilmiş ancak dış dünyaya tanımlanmamıştır). Muhtemelen bir pimplC ++ 'la aynı şekilde daha güçlü bir bilgi gizleme biçimidir .

Evet, insanların OOP'yi C'de nasıl uyguladıklarını biliyorum, teşekkür ederim. Demek istediğim, yapıcıların "doğrudan OOP için bir önkoşul olarak kabul edilmediğini" belirttiğiniz ifadesinin yanlış olduğuydı.
Nicol Bolas

Anladım, doğru demiştim ... ama bu durumda C'nin yıkıcılar ve inşaatçılar için (yeterli?) Destek sağladığını söyleyebilir miyiz?

-1

Kötü bir soru değil.

C'ye bir OO dili diyecekseniz, OO'nun hemen hemen tüm işlemsel dilleri de aramanız gerekir. Yani bu terimi anlamsız hale getirirdi. c, OO için dil desteğine sahip değil. Yapıları varsa, ancak yapıları typessınıf değildir.

Aslında c çoğu dile kıyasla çok fazla özelliğe sahip değildir. Çoğunlukla kütüphanesi dahil olmak üzere hızı, sadeliği, popülerliği ve desteği için kullanılıyor.

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.