Korunan yöntemler için gerçek dünya senaryoları


14

Bugün temelde hiçbir zaman protectedC ++ kodunda yöntemleri kullanmadım , çünkü nadiren bir ebeveynin genel olmayan yöntemlerini çağırma ihtiyacını hissediyorum. Java'da korumalı şablon yöntem desenini kullanıyorum, ancak C ++ özel yöntemlerini geçersiz kılabildiğiniz için, protectedorada da ihtiyacım yok.

Peki protectedC ++ kodunda yöntemleri kullanmak isteyeceğim bazı gerçek dünya senaryoları nelerdir?

(Genel olarak uygulama mirasına çok düşkün olmadığımı, bunun çok fazla açıklayabileceğini unutmayın ...)

Yanıtlar:


12

İşte bir örnek

class Base {
public:
  // other members ...

protected:
  ~Base() { }
};

Polimorfik olmayan bir baz sınıfı olarak kullanılır. Ancak delete baseptr;, yıkıcıya erişilemediğinden kullanıcıların aramasına izin verilmeyecektir . Sanal bir yıkıcı olmadığından, insanların bunu yapmasına izin vermek tanımsız bir davranış olacaktır. Herb'in "Sanallık" konusuna bakın .


1
Senin neyin var arkadaşlar? Bu neden reddedildi? Mükemmel mantıklı. Eğer anlamadıysanız, lütfen sorun. Yanlış olduğunu düşünüyorsanız, lütfen açıklayın. Görüşlerinizden öğrenmek için buradayız.
sbi

Neden -1? İlk düşündüğüm şey bu.
GManNickG

1
Yapıcılar ve Yıkıcılar gördüğüm tek kullanımla ilgilidir. Gcc'nin hala yıkıcıya ilişkin sanal olmayan bir uyarı verdiğini unutmayın.
Matthieu M.Mar

+1 Ayrıca bazı kitap tavsiyeleri uygulamak için korumalı yöntemi kullanıyorum: genel sanal işlevler yerine korumalı sanal işlevlere sahip bir genel arabirime sahip olmak.
Klaim

3

Sık kullandığım bir örnek, nesne Hiyerarşimin Temel Sınıfında korumalı bir Kaydediciye sahip olacağım. Tüm temel sınıflarımın Logger'a erişmesi gerekecek, ancak bunu herkese açık hale getirmek için bir neden yok.

Ayrıca, Şablon kalıbı kullanıyorsanız ve temel sınıfta yürütme öncesi veya yürütme yönteminiz varsa, temel uygulamayı geçersiz kılma yönteminden çağırmak isteyebilirsiniz. Taban yalnızca özelse (ve yine de C ++ ile üzerine yazılabiliyorsa), temel uygulamayı geçersiz kılma yönteminden çağıramazsınız.


1
Şablon kalıbı temel sınıf yöntemlerini çağırmak zorunda değil mi ???
sbi

Nokta alınan, ama temel sınıf yöntemleri çağırmak zorunda değil 'hepsi' olduğunu söyleyemem. Birçok durumda, her biri biraz daha fazla işlevsellik / denetim ekleyen birden çok düzeyi olan şablon desenini uygulayan nesne hiyerarşileri var. Bu durumlarda, Korumalı bir yöntem gerekli olacaktır.
bryanatkinson

1

Sadece geçmişte kullandığım bir örnek. Korumalı yöntemler, uygulamaya özgü işlevler sağlamak için mükemmeldir, aynı zamanda temel sınıfın bir şeyleri düzgün bir şekilde izlemesine izin verir. Geçersiz kılınabilir bir başlatma işlevi sağlayan, ancak başlatılıp başlatılmadığını belirlemek için duruma sahip olması gereken bir temel sınıf düşünün:

class Base
{
private:
    bool m_bInitialized;
public:
    virtual void Initialize() = 0;

    void setInitialized() { m_bInitialized = true; };
    bool isInitialized() const { return m_bInitialized; };
}; // eo class Base

Burada her şey iyi ve güzel. Türetilmiş bir sınıf, hiç setInitialized()kimsenin onu arayabileceği gerçeğini aramakla uğraşmadığı sürece (bunu burada koruyabiliriz ve korumalı yöntemleri kullanmak için başka bir neden!). Sanal korumalı üyeleri kullanan bir sınıfı tercih ederim:

class Base
{
private: 
    bool m_bInitialized;

protected:
    virtual void InitializeImpl() = 0;

public:

    void Initialize()
    {
        InitializeImpl();
        m_bInitialized = true;
    }; // eo Initialize

    bool isInitialized() const { return m_bInitialized; };
}; // eo class Base

Yeni sınıfımızda, tüm başlatma hala türetilmiş sınıfa devredilir. Atılan istisna olması durumunda, yöntemimizin gerçekleşeceğini söylediği "bu sınıf başlatıldı" sözleşmesini sürdürüyoruz.


0

Diğer birçok özellik gibi, protectedkapsüllemeyi bir dereceye kadar kırmanıza izin verir. Saf OO kavramlarını kırmak genellikle birkaç nedenden dolayı yapılır

  1. daha iyi performans elde etmek (düşünmek inline),
  2. kodun daha kolay anlaşılmasını ve ironik olarak
  3. daha iyi kapsülleme ( friendsınıf üyelerine erişimi birkaç arkadaşla kısıtlamanızı sağlar)

ve protectedbu kutudaki araçlardan sadece biri. Türetilmiş sınıflara, bir sınıfın genel halktan gizlenmesi gereken bazı bölümlerine erişim vermek istiyorsanız kullanabilirsiniz.

Bunu kullandığım bir örnek, bir sınıfın tüm kurucularını yapmak protected, temelde o sınıfı soyut yapmaktır (türetilmiş bir sınıfın bir nesnesinin bir alt nesnesi dışında başlatamazsınız).


0

Belki de kötü tasarımdı, ama böyle bir şey için vardı:

// much simplified, of course
class input_device // base class
{
public:
    virtual ~input_device() {}

    // normally would be private with public caller, etc.
    virtual void update() = 0; 

    template <typename Func>
    void register_callback(Func func)
    {
        mButtonPressSignal.connect(func);
    }

protected:
    void trigger_signal(unsigned button)
    {
        mButtonPressSignal(button);
    }

private:
    boost::signals2::signal<void(unsigned)> mButtonPressSignal;
};

Türetilmiş sınıflar, update()arayarak sinyali tetikleyebilir trigger_signal(). Ancak, sinyalle yapabilecekleri tek şey bu olduğu için, sinyalin kendisi gizli kaldı. Tetikleme işlevi korunmuştur çünkü hiçbir şey değil, yalnızca türetilmiş sınıf onu tetikleyebilmelidir.


0

"Genel Yöntemler": Bir sınıf bunu yapabilir. "Korumalı Yöntemler": Bir sınıf bunu nasıl yapabilir? "Özel Yöntemler": Bir sınıf bunu nasıl yapabilir, ama "Paranoyakım ve kimsenin bunu nasıl yaptığımı bilmesini istemiyorum".

// burguers.hpp

class BurguerClass {
  private: void addSecretRecipeSauce();  

  protected: virtual void addBread();  
  protected: virtual void addSalad();  
  protected: virtual void addMeat();
  protected: virtual void addExtraIngredients();

  public: virtual void makeBurguer();  
}

class CheeseBurguerClass: public BurguerClass {
  protected: override void addBread();  
  protected: override void addSalad();  
  protected: override void addMeat();
  protected: override void addExtraIngredients();

  protected: virtual void addCheese();

  public: override void makeBurguer();
}

class RanchStyleBurguerClass: public BurguerClass {
  protected: override void addBread();  
  protected: override void addSalad();  
  protected: override void addMeat();
  protected: override void addExtraIngredients();

  public: override void makeBurguer();
}

class EastCoastVegetarianStyleBurguerClass: public BurguerClass {
  protected: override void addBread();  
  protected: override void addSalad();  
  protected: override void addMeat();
  protected: override void addExtraIngredients();

  public: override void makeBurguer();
}

Böylece, fast food restoranınıza yeni bir aşçı (geliştirici) gelir. Öğretirsiniz, burguer satarsınız (genel yöntemler), burguerlerin nasıl hazırlanacağı (korunan yöntemler), ancak "patentli" gizli tarif sosunu kendinize saklayın.

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.