2010-11-04 5 views
6

Kodlamayı (bazı yardımlarla) dün sona erdirdim:Bir üyenin erişim seviyesini değiştirmek nasıl ve neden mümkündür?

#include <iostream> 

using namespace std; 

class A 
{ 
    public: 
     virtual void foo(){cout << "A::foo\n";} 
}; 

class B : private A 
{ 
    private: 
     virtual void foo(){ cout << "B::foo\n";} 
     void DoSomething(SomeOtherClass& o){o.DoSomething(*static_cast<A*>(this));} 
}; 

Miras yöntemini değiştirmeyi denedim:

class B : public A 
{ 
    private: 
     virtual void foo(){ cout << "B::foo\n";} 
}; 

int main() 
{ 
    A* a = new B; 
    a->foo(); 
} 

Bu hala çalışıyor. Derleme zamanı hatası bekleniyor. Lütfen bunun neden mümkün olduğunu ve olası kullanımların neler olduğunu söyle? İlk senaryo nedeniyle bir kullanım biliyorum - Farklı sınıflar için farklı arayüzler ortaya çıkarabilir.

DÜZENLEME:

İkinci durumda çıktı B::foo.

+0

Hatayı nereden buldunuz?İşlevin özel olarak bildirilmesi üzerine mi? Ya da işlevin çağrılması üzerine? –

+0

Şaşırdım. Bu özelliğin olası kullanımlarını açıklayabilecek bir cevabı umuyoruz (?). Bir kullanım, programcıyı, arabirimini kullanmak için B sınıfının bir işaretçisi olarak B sınıfını başlatması için zorlamak olabilir. Ama neden bu iyi bir şey olurdu, bilmiyorum. – manneorama

+0

@PigBen: İkinci durumda, 'B' içindeki foo'nun tanımındaki hatayı bekledim. – nakiya

cevap

1

Tüm sorularınızı doğrudan yanıtlamayabilir, ancak gelecekteki başvurular için buraya koymaya karar verdim. Ayrıca, bunu bir tutam tuz ile alınız, çünkü bu, C++ Standart dünyasında gerçekleşmiş olan olayları anlamamıza dayanmaktadır.

this. Benimle ARM'm yok ama makale gerekli detayları veriyor. C++ 0x ile

Not 115

115) Erişim beyanlar kaldırılmış diyor; (7.3.3) numaralı raporlar, aynı şeyleri yapan 'un daha iyi bir yolunu sunar. C++ dilinin önceki sürümlerinde, erişim bildirimleri daha sınırlıydı; genelleştirilmiş ve eşdeğerliğini sadeliğinde kullanma beyanlarına eşdeğer olarak yapılmıştır. Programcılar, yeni kodda erişim bildirimlerinin yeni yeteneklerinden ziyade, bildirimleri kullanılarak kullanılmaları için teşvik edilen 'dur. Özetle

:

Ben ARM başlangıçta yasak düşünüyorum:

bir erişim beyanı temel sınıfta erişilebilir bir üyesi erişimi kısıtlamak için kullanılamaz, veya , taban sınıfında erişilemeyen bir üyesine erişimi etkinleştirmek için kullanılabilir.

Ama daha sonra ben Standart derleme zamanında derleyici yalnızca a temel sınıf için bir işaretçi olduğunu görebiliriz, çünkü bu A ve foo() bir kamu yöntemdir çalışır this was eventually allowed

+0

"sonunda izin verildi" iyi, şimdi, kullanımdan kaldırıldılar. Bu cevabın daha iyi bir teklifi vardı: http://stackoverflow.com/questions/2084801/c-using-declaration-scope-and-access-control –

3
using namespace std; 

class A 
{ 
    public: 
     virtual void foo(){cout << "A::foo\n";} 
}; 

class B : public A 
{ 
    private: 
     virtual void foo(){ cout << "B::foo\n";} 
}; 

int main() 
{ 
    A* a = new B; 
    a->foo(); 
} 

gelişti zaman tahmin Mükemmel olarak geçerli olan a numaralı telefondan aranıyor. Sanal bağlanma derlemeden sonraki çalışma zamanında dinamik olarak gerçekleşir, bu virtaul bağlaması, gerçek aramanın, sanallaştırmanın kullanılma performansının cezası olan ve A::foo()'a karar vermesine karar verir.

+0

Neden işe yaradığını görmek kolay. Ancak, eğer foo() 'nun B'ye özel olarak yapılmasına izin verilmediyse, çok daha anlamlı olurdu. Dolayısıyla, bu sorunun, tasarım kararının ardındaki mantığın ne olduğunu düşünüyorum. –

+0

@kotlinski: Bu mantığı kullanan "Şablon yöntemi" deseni denilen çok ünlü bir tasarım deseni var. Lütfen bunu kontrol et. –

+1

Bu ve şablon yöntemi tasarım deseni arasındaki bağlantıyı göremiyorum. – nakiya