Neden aynı sınıftaki nesnelerin birbirlerinin özel verilerine erişimi var?


99

Neden aynı sınıftaki nesnelerin birbirlerinin özel verilerine erişimi var?

class TrivialClass {
public: 
  TrivialClass(const std::string& data) :
    mData(data) {};

  const std::string& getData(const TrivialClass& rhs) const {
    return rhs.mData;
  };

private:
  std::string mData;
};

int main() {
  TrivialClass a("fish");
  TrivialClass b("heads");

  std::cout << "b via a = " << a.getData(b) << std::endl;
  return 0;
}

Bu kodlar çalışıyor. A nesnesinin özel verilere b nesnesinden erişmesi ve onu geri getirmesi tamamen mümkündür. Bu neden böyle olsun? Özel verilerin özel olduğunu düşünürdüm. (Pimpl deyimindeki kopya kurucuları anlamaya çalışarak başladım, ancak sonra bu basit durumu bile anlamadığımı keşfettim.)


18
Başlangıç ​​noktası olarak, en basit sınıflar dışında herhangi bir kopya-yapıcıyı düzgün bir şekilde uygulayamazsınız. Sınıfları kendi en iyi arkadaşları olarak düşünebilirsiniz :-)
Cameron

4
Müşterilerinden özel düşünün, ancak sınıftaki tüm çalışanların erişimi var
Martin Beckett

Teşekkürler Cameron. Bu mantıklı, ancak o zaman neden bu erişim yalnızca kopya oluşturucular ve atama operatörleriyle sınırlı değil?
Keith

5
Aynı türden nesneler genellikle çok etkileşim halindedir. Ve kimse sizi başka bir örneğin özel verilerini dağıtan bir yöntem yazmaya zorlamaz. :)
UncleBens

4
Basitçe, derleme sırasında derleyicinin aynı nesneyi tanımlamanın bir yolu olmadığı için. Bu tür erişimi zorunlu kılmak, çalışma zamanı desteği gerektirecektir.
Chethan

Yanıtlar:


80

Çünkü C ++ 'da böyle çalışır. C ++ 'da erişim kontrolü nesne bazında değil, sınıf bazında çalışır .

C ++ 'da erişim denetimi, statik, derleme zamanı özelliği olarak uygulanır. Derleme zamanında herhangi bir anlamlı nesne başına erişim denetimi uygulamanın gerçekten mümkün olmadığının oldukça açık olduğunu düşünüyorum. Bu şekilde yalnızca sınıf başına kontrol uygulanabilir.

Nesne başına kontrolün bazı ipuçları korumalı erişim özelliklerinde mevcuttur, bu nedenle standartta (11.5) kendi özel bölümü bile vardır. Ancak yine de burada tanımlanan nesne başına özellikler oldukça temeldir. Yine, C ++ 'daki erişim kontrolünün sınıf bazında çalışması amaçlanmıştır.


9
+1. C ++, derleme zamanı mekanizmalarında büyüktür, çalışma zamanı mekanizmalarında çok büyük değildir. Oldukça iyi bir genel kural.
Nemo

4
"Derleme zamanında herhangi bir anlamlı nesne başına erişim denetimi uygulamak gerçekten mümkün değildir". Neden olmasın? İçinde void X::f(X&x), derleyici kolayca ayırt edebilir this->ave x.a. Derleyicinin bunu bilmesi (her zaman) mümkün değildir *thisve çağrılırsa xaslında aynı nesnedir x.f(x), ancak bir dil tasarımcısının bunu Tamam bulduğunu çok iyi görebilirim.
André Caron

@ AndréCaron Bence bu aslında çok daha büyük bir su ısıtıcısı balık, o zaman bunu yaparsınız. Satır içi oluşturma gerçekleşmediğinde, derleyicinin her zaman aynı olup olmadığını thisve olup olmadığını kontrol &xetmesi gerekir. Bu aslında bile bir sorun olmaktan biter Bunu yapmak için kötü X::f(Y& y)bizim somut nesne türünün olabileceğini, çünkü Zo hem devralır Xve Y. Kısacası, gerçek bir karmaşa, performant değil, MI ile mantıklı bir şekilde çalışmak zor.
Nir Friedman

@NirFriedman Sanırım öneriyi yanlış anladınız. Derlerken X::f(X& x)erişim varsa x.a, derlenmez. Başka hiçbir şey değişmez, kontrollerin eklenmesi gerekmez, bu nedenle hala geçerli programların performansı etkilenmez. Ve mevcut C ++ 'da bir kırılma değişikliği olarak önerilmiyor, ancak tasarımcıların privateorijinal olarak tanıtırken yapabileceği bir şey olarak öneriliyor .
Alexey Romanov

31

"Gizli", "Resimlerimi facebook'ta özel yaptım, böylece onları göremezsin" anlamında bir erişim kontrol mekanizması değil.

C ++ 'da "özel", bunların sizin (sınıfın kodlayıcısının) gelecekteki sürümlerde vb. Değiştirebileceğiniz bir sınıfın parçaları olduğunu ve sınıfınızı kullanan diğer kodlayıcıların onların varlığına veya işlevselliğine güvenmesini istemediğinizi söyler. .

Gerçek erişim kontrolü istiyorsanız, gerçek veri güvenliği tekniklerini uygulamalısınız.


13

Bu güzel bir soru ve son zamanlarda bu soruyla karşılaştım. Meslektaşlarımla bazı tartışmalar yaptım ve işte tartışmamızın özeti: Bu tasarım gereğidir. Bu tasarımın tüm durumlar için tamamen makul olduğu anlamına gelmez, ancak sınıf başına özel seçildiğinde neden bazı hususlar olmalıdır. Düşünebileceğimiz olası nedenler şunları içerir:

Her şeyden önce, örnek başına erişim kontrolünün maliyeti çok yüksek olabilir. Bu konu bu başlıkta başkaları tarafından tartışılmıştır. Teorik olarak, bu, bu işaretçi kontrolü ile yapılabilir . Ancak bu, derleme zamanında yapılamaz ve yalnızca çalışma zamanında yapılabilir. Bu nedenle, çalışma zamanında her üyenin erişim kontrolünü belirlemeniz gerekir ve ihlal edildiğinde muhtemelen yalnızca istisnalar ortaya çıkacaktır. Maliyet yüksektir.

İkinci olarak, sınıf başına erişim denetiminin, kopya oluşturucu veya işleç = gibi kendi kullanım durumu vardır. Erişim kontrolü örnek başına ise bunları uygulamak zor olacaktır.

Ayrıca, erişim kontrolü, verilere değil, koda / üyeye erişimin nasıl modüler hale getirileceği / kontrol edileceği için temel olarak programlama / dil perspektifinden gelir.


12

Bu biraz keyfi bir dil tasarım kararı. Örneğin Ruby'de , private"yalnızca örnek kendi özel veri üyelerine erişebilir" gibi gerçekten özel anlamına gelir. Ancak bu biraz kısıtlayıcıdır.

Yorumlarda belirtildiği gibi, kopya oluşturucular ve atama işleçleri, başka bir örneğin özel veri üyelerine doğrudan eriştiğiniz ortak yerlerdir. Bunun daha az açık nedenleri var.

Aşağıdaki durumu düşünün. OO bağlantılı bir liste uyguluyorsunuz. Bağlantılı liste, işaretçileri yönetmek için yuvalanmış bir düğüm sınıfına sahiptir. Bu düğüm sınıfını, işaretçileri kendisi yönetecek şekilde uygulayabilirsiniz (işaretçilerin genel ve liste tarafından yönetilmesi yerine). Böyle bir durumda, diğer düğüm nesnelerinin işaretleyicilerini, tipik kopyalama yapıcısı ve atama operatörünün olduğu diğer yerlerde değiştirmek isteyen düğüm nesnelerine sahip olursunuz.


4

Hile verisi olduğunu hatırlamak privateiçin sınıfın değil, örnek sınıfın. Sınıfınızdaki herhangi bir yöntem, o sınıfın herhangi bir örneğinin özel verilerine erişebilir; Diğer örneklerin özel veri üyelerine açıkça erişen yöntemleri yasaklamadığınız sürece verileri bir örnek içinde gizli tutmanın bir yolu yoktur.


1

Yukarıdaki tüm yanıtlara ek olarak, özel kopya oluşturucularını, atama operatörlerini ve diğer örnekler üzerinde çalışan bir sınıf için yazacağınız diğer tüm işlevleri göz önünde bulundurun . Tüm bu veri üyeleri için erişimci işlevlerine ihtiyacınız olacaktır.


-8

Özel veriler, ona erişimi olan biri başkasına ifşa edene kadar gizli kalır.

Bu kavram aşağıdakiler gibi diğer durumlar için de geçerlidir:

class cMyClass
{
public:
   // ...
   // omitted for clarity
   // ...

   void Withdraw(int iAmount)
   {
      iTheSecretVault -= iAmount;
   }

private:
   int iTheSecretVault;
};

Bir kimse parayı nasıl çekebilir? :)


3
Bu örnek, başka bir örneğin özel veri üyelerine erişen bir sınıf örneğini içermez.
André Caron

@Andre, "Bu kavram ... gibi diğer durumlar için de geçerlidir."
YeenFei

^ "Öteki durum" konu dışı olan tanım gereği, sizin örnek konuyla ilgili değildir (ve o da başka bir yerde bilgilendirici olurdu emin değilim) bu yüzden
underscore_d

1
Bu soruya hiç de doğru bir açıklama değil.
Panda
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.