Skenario dunia nyata untuk metode yang dilindungi

14

Hari ini saya perhatikan bahwa saya pada dasarnya tidak pernah menggunakan protectedmetode dalam kode C ++, karena saya jarang merasa perlu memanggil metode non-publik dari orang tua. Saya menggunakan protected di Java dalam pola metode templat, tetapi karena Anda bisa mengganti metode pribadi dalam C ++, saya juga tidak perlu protectedmelakukannya.

Jadi apa sajakah skenario dunia nyata di mana saya ingin menggunakan protectedmetode dalam kode C ++?

(Perhatikan bahwa saya tidak terlalu menyukai warisan implementasi, yang mungkin menjelaskan banyak hal ...)

fredoverflow
sumber

Jawaban:

12

Berikut ini sebuah contoh

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

protected:
  ~Base() { }
};

Digunakan sebagai kelas dasar non-polimorfik. Tetapi pengguna tidak akan diizinkan untuk memanggilnya delete baseptr;karena destruktor tidak dapat diakses. Karena tidak memiliki destruktor virtual, memungkinkan orang untuk melakukan itu adalah perilaku yang tidak terdefinisi. Lihat "Virtualitas" oleh Herb.

Johannes Schaub - litb
sumber
1
Ada apa dengan kalian? Mengapa ini diturunkan? Sangat masuk akal. Jika Anda tidak memahaminya, silakan tanyakan. Jika Anda merasa itu salah, mohon jelaskan. Kami di sini untuk belajar dari wawasan Anda.
sbi
Kenapa -1? Ini adalah hal pertama yang saya pikirkan.
GManNickG
1
Konstruktor dan Destructor hanya tentang kegunaan yang saya lihat. Perhatikan bahwa gcc masih memancarkan peringatan bahwa destruktor non-virtual untuk yang satu ini.
Matthieu M.
+1 Saya juga menggunakan metode yang dilindungi untuk menerapkan beberapa saran buku: memiliki antarmuka publik dengan fungsi virtual yang dilindungi, alih-alih fungsi virtual publik.
Klaim
3

Salah satu contoh yang sering saya gunakan adalah bahwa di Kelas Dasar objek saya Hierarki saya akan memiliki Logger yang dilindungi. Semua kelas dasar saya akan membutuhkan akses ke Logger, tetapi tidak ada alasan untuk membuatnya dapat diakses publik.

Juga, jika Anda menggunakan pola Templat, dan Anda memiliki metode eksekusi sebelum atau sesudah pada kelas dasar, Anda mungkin ingin memanggil implementasi basis dari metode utama. Jika basis hanya pribadi (dan masih bisa ditimpa dalam C ++), Anda tidak akan dapat memanggil implementasi basis dari metode penimpaan.

bryanatkinson
sumber
1
Bukankah semua pola templat tentang tidak harus memanggil metode kelas dasar ???
sbi
Poin yang diambil, tapi saya tidak akan mengatakan itu semua tentang tidak harus memanggil metode kelas dasar. Dalam banyak situasi, saya memiliki hierarki objek yang menerapkan pola templat yang memiliki beberapa level, yang masing-masing menambah sedikit fungsionalitas / pemeriksaan. Dalam kasus ini, metode yang dilindungi akan diperlukan.
bryanatkinson
1

Hanya sebuah contoh yang pernah saya gunakan di masa lalu. Metode yang dilindungi sangat bagus untuk menyediakan fungsi implementasi spesifik, sementara juga memungkinkan kelas dasar untuk melacak hal-hal dengan benar. Pertimbangkan kelas dasar yang menyediakan fungsi inisialisasi yang dapat ditimpa, tetapi juga harus memiliki status untuk menentukan apakah diinisialisasi:

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

Semua baik-baik saja di sini. Kecuali ketika kelas turunan tidak repot-repot memanggil setInitialized()fakta bahwa siapa pun dapat menyebutnya (kita bisa membuat ini terlindungi di sini, dan alasan lain untuk menggunakan metode yang dilindungi!). Saya lebih suka kelas yang menggunakan anggota yang dilindungi virtual:

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

Di kelas baru kami, semua inisialisasi masih didelegasikan ke kelas turunan. Asalkan pengecualian telah dilempar, kami mempertahankan kontrak "kelas ini diinisialisasi" yang menurut metode kami akan terjadi.

Jus Moo
sumber
0

Seperti banyak fitur lainnya, protectedAnda dapat memecah enkapsulasi hingga beberapa perluasan. Melanggar konsep OO murni biasanya dilakukan karena beberapa alasan

  1. mencapai kinerja yang lebih baik (pikirkan inline),
  2. membuat kode lebih mudah dimengerti, dan, ironisnya,
  3. enkapsulasi yang lebih baik ( friendmemungkinkan Anda membatasi akses ke anggota kelas ke beberapa teman)

dan protectedhanya salah satu alat di dalam kotak itu. Anda dapat menggunakannya jika Anda ingin memberikan kelas turunan akses ke beberapa bagian kelas yang harus disembunyikan dari masyarakat umum.

Satu kasus di mana saya telah menggunakannya adalah untuk membuat semua konstruktor dari suatu kelas protected, pada dasarnya membuat kelas itu abstrak (Anda tidak bisa instantiate kecuali sebagai sub-objek dari objek dari kelas turunan).

sbi
sumber
0

Mungkin itu desain yang buruk, tetapi saya memilikinya untuk sesuatu seperti ini:

// 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;
};

Kelas turunan, dalam update(), dapat memicu sinyal dengan memanggil trigger_signal(). Tetapi karena hanya itu yang harus mereka lakukan dengan sinyal, sinyal itu sendiri dibiarkan pribadi. Fungsi pemicu dibuat terlindungi karena hanya kelas turunan yang dapat memicunya, bukan apa-apa sama sekali.

GManNickG
sumber
0

"Metode Publik": Kelas dapat melakukan ini. "Metode Terlindungi": Bagaimana kelas dapat melakukan ini. "Metode Pribadi": Bagaimana kelas dapat melakukan ini, tetapi "Saya paranoid dan tidak ingin ada yang tahu bagaimana saya melakukannya".

// 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();
}

Jadi, juru masak baru (pengembang) tiba di restoran cepat saji Anda. Anda mengajarkannya, Anda menjual burguers (metode umum), cara menyiapkan burguers (metode yang dilindungi), tetapi simpan saus resep rahasia yang "sudah dipatenkan" untuk Anda sendiri.

umlcat
sumber