Özel değişkenler neden genel olarak erişilebilir başlık dosyasında açıklanıyor?


11

Tamam, umarım bu Programcılar için yeterince öznel bir soru, ama işte gidiyor. Diller ve yazılım mühendisliği uygulamaları hakkındaki bilgilerimi sürekli genişletiyorum ... ve benim için hiçbir anlam ifade etmeyen bir şeyle karşılaşıyorum.

C ++ 'da, sınıf bildirimleri private:, başlık dosyasındaki teorik olarak, bunları bir lib yaparsanız eklemek için kullanıcıya ilettiğiniz yöntem ve parametreleri içerir.

Objective-C'de, @interfacehemen hemen aynı şeyi yapın, sizi özel üyelerinizi listelemeye zorlayın (en azından uygulama dosyasında özel yöntemler almanın bir yolu vardır).

Söyleyebileceğim kadarıyla, Java ve C #, herkesin erişebileceği tüm özellikleri / yöntemleri bildirebilen ve kodlayıcıya uygulama dosyasındaki tüm uygulama ayrıntılarını gizleme olanağı veren bir arabirim / protokol sağlamanıza izin verir .

Neden? Kapsülleme OOP'nin temel ilkelerinden biridir, C ++ ve Obj-C neden bu temel yeteneklerden yoksundur? Obj-C veya C ++ için tüm uygulamayı gizleyen bir tür en iyi uygulamalar var mı?

Teşekkürler,


4
Acını hissediyorum. Bir sınıfa özel bir alan ilk kez ekledi ve onu kullanan her şeyi yeniden derlemek zorunda kaldı C ++ çığlık kaçtı.
Larry Coleman

@Larry, çok fazla umursamıyorum, ama büyük bir OO dili olarak müjdelendi, ancak "düzgün" bile kapsülleyemiyor.
Stephen Furlani

2
Yutturmacaya inanma. Hem statik hem de dinamik yazma kamplarında OO yapmanın daha iyi yolları vardır.
Larry Coleman

Bazı açılardan harika bir dil, ancak Simula 67'nin C'ye aşılanması olan OO yetenekleri nedeniyle değil
David Thornley

Biraz C programlaması yapmalısınız. Daha sonra bu diller vb Java C # dahil oldukları gibi niçin daha iyi bir anlayış olacak
Henry

Yanıtlar:


6

Soru, derleyicinin bir nesnenin ne kadar büyük olduğunu bilmesi gerekip gerekmediğidir. Eğer öyleyse, derleyici onları sayabilmek için özel üyeler hakkında bilgi sahibi olmalıdır.

Java'da ilkel türler ve nesneler vardır ve tüm nesneler ayrı olarak ayrılır ve bunları içeren değişkenler gerçekten işaretçilerdir. Bu nedenle, bir işaretçi sabit boyutlu bir nesne olduğundan, derleyici, sivri uçlu nesnenin gerçek boyutunu bilmeden bir değişkenin ne kadar büyük bir şeyi temsil ettiğini bilir. Yapıcı bunların hepsini halleder.

C ++ 'da, nesnelerin yerel olarak veya yığın üzerinde temsil edilmesi mümkündür. Bu nedenle, derleyicinin bir nesnenin ne kadar büyük olduğunu bilmesi gerekir, böylece yerel bir değişken veya dizi ayırabilir.

Bazen sınıf işlevselliğini genel bir arayüze ve özel her şeye bölmek istenir ve PIMPL (İşaretçiden İMPLementasyona) tekniğinin devreye girdiği yer budur. Sınıfın özel bir uygulama sınıfına bir işaretçisi olacaktır ve genel sınıf yöntemleri arayabilir söyledi.


derleyici bu bilgiyi almak için nesne kitaplığına bakamıyor mu? Bu bilgiler neden insan tarafından okunabilir yerine makinede okunamıyor?
Stephen Furlani

@Stephen: Derleme sırasında bir nesne kütüphanesi olması gerekmez. Nesnelerin boyutu derlenmiş kodu etkilediğinden, sadece bağlantı zamanında değil, derleme zamanında da bilinmelidir. Ayrıca Ah'nin A sınıfı, Bh'yi tanımlaması için B sınıfı tanımlaması ve A.cpp'deki fonksiyon tanımlarının B sınıfı nesneleri kullanması ya da tam tersi mümkündür. Bu durumda, nesne kodundan nesne boyutu alınıyorsa, A.cpp ve B.cpp öğelerinin her birini diğerinden önce derlemek gerekir.
David Thornley

derleme sırasında bağlantı yapılamıyor mu? Ayrıntıları bu derinlikte bilmediğimi itiraf ediyorum, ancak bir nesnenin arayüzü içeriğini açığa çıkarırsa, aynı içerikler bir kitaplıktan veya makine tarafından okunabilen başka bir bileşenden açığa çıkamaz mı? herkesin erişebileceği bir başlık dosyasında tanımlanmaları gerekir mi? Bu C dillerinin çoğunda parçası olduğunu anlamak, ancak vermez var bu yüzden olunur?
Stephen Furlani

1
@Stephen: Bağlama yalnızca derleme sırasında tüm uygun bileşenler varsa yapılabilir. O zaman bile, bu, kısmi derleme (nesne boyutları hariç her şey), kısmi bağlama (nesne boyutlarını almak için), daha sonra son derleme ve bağlama içeren karmaşık bir süreç olacaktır. C ve C ++ 'ın nispeten eski diller olduğu düşünüldüğünde, bu gerçekleşmeyecekti. Muhtemelen birileri başlık dosyaları olmadan yeni bir dil tasarlayabilir, ancak C ++ olmazdı.
David Thornley

14

C ++ tasarımından dolayı, yığın üzerinde bir nesne oluşturmak için derleyici ne kadar büyük olduğunu bilmelidir. Bunu yapmak için, başlık dosyasında tüm alanların bulunması gerekir, çünkü derleyicinin başlık eklendiğinde görebileceği tek şey budur.

Örneğin bir sınıf tanımlarsanız

class Foo {
    public int a;
    private int b;
};

Sonra sizeof(Foo)ise sizeof(a) + sizeof(b). Özel alanları ayırmak için bir mekanizma varsa, başlık şunları içerebilir:

class Foo {
    public int a;
};

ile sizeof(Foo) = sizeof(a) + ???.

Özel verileri gerçekten gizlemek istiyorsanız, pimpl deyimini deneyin.

class FooImpl;
class Foo {
    private FooImpl* impl;
}

başlık ve FooImplyalnızca Foouygulama dosyasında bir tanım .


Ah. Durumun bu olduğu hakkında hiçbir fikrim yoktu. Java, C # ve Obj-C gibi dillerin sınıfa ne kadar büyük olması gerektiğini sorabilmeleri için "Sınıf Nesneleri" var mı?
Stephen Furlani

4
Özel bir uygulamaya işaret eden bir pimpl kullanmayı deneyin. Tüm sınıf işaretçileri aynı boyutta olduğundan, uygulama sınıfını tanımlamanız gerekmez, yalnızca bildiriniz.
Scott Wales

Bunun bir yorum yerine bir cevap olması gerektiğini düşünüyorum.
Larry Coleman

1

Tüm bunlar tasarım seçimine bağlı.

C ++ veya Objective-C sınıfının özel uygulama ayrıntılarını gerçekten gizlemek istiyorsanız, sınıfın desteklediği bir veya daha fazla arabirim sağlarsınız (C ++ salt sanal sınıf, Objective-C @protocol) ve / veya sınıfı yaparsınız statik bir fabrika yöntemi veya bir sınıf fabrikası nesnesi sağlayarak kendini inşa edebilir.

Özel değişkenlerin başlık dosyası / sınıf bildirimi / @ arabiriminde gösterilmesinin nedeni, sınıfınızın bir tüketicisinin bunun yeni bir örneğini oluşturması ve bir new MyClass()veya [[MyClass alloc]init]istemci kodundaki bir derleyicinin ne kadar büyük olduğunu anlamak için derleyiciye ihtiyacı olmasıdır. nesne ayırma yapmaktır.

Java ve C # 'da sınıfta ayrıntılı olarak özel değişkenleri vardır - bunlar bir istisna değildir, ancak IMO arabirim paradigması bu dillerde çok daha yaygındır. Her durumda kaynak kodunuz olmayabilir, ancak derlenmiş / bayt kodunda bu bilgileri çıkarmak için yeterli meta veri vardır. C ++ ve Objective-C bu meta verilere sahip olmadığından, tek seçenek class / @ arabiriminin gerçek ayrıntılarıdır. C ++ COM dünyasında, herhangi bir sınıfın özel değişkenlerini açığa çıkarmazsınız ancak sınıf dosyası sağlayabilir (çünkü sınıf saf sanaldır). Bir sınıf fabrikası nesnesi de gerçek örnekleri oluşturmak için kaydedilir ve çeşitli biçimlerde bazı meta veriler vardır.

C ++ ve Objective-C'de, başlık dosyasını dağıtmak ek bir arabirim / @ protokol dosyası yazmak ve sürdürmekle karşılaştırıldığında daha az iştir. Özel uygulamanın bu kadar sık ​​maruz kalmasının bir nedeni de budur.

C ++ 'da başka bir neden şablonlardır - derleyici, sağlanan parametreler için uzmanlaşmış bir sınıfın sürümünü oluşturmak için sınıfın ayrıntılarını bilmelidir. Sınıf üyelerinin boyutu parametreleştirmeye göre değişir, bu nedenle bu bilgiye sahip olması gerekir.

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.