สถานการณ์ในโลกแห่งความเป็นจริงสำหรับวิธีการป้องกัน


14

วันนี้ฉันสังเกตเห็นว่าโดยทั่วไปฉันไม่เคยใช้protectedวิธีการในรหัส C ++ เพราะฉันไม่ค่อยรู้สึกว่าจำเป็นต้องเรียกวิธีการที่ไม่ใช่แบบสาธารณะของผู้ปกครอง ฉันใช้การป้องกันใน Java ในรูปแบบวิธีการแม่แบบ แต่เนื่องจากคุณสามารถแทนที่วิธีส่วนตัวใน C ++ ฉันไม่จำเป็นต้องprotectedมี

ดังนั้นสถานการณ์จริงที่ฉันต้องการใช้protectedวิธีการในรหัส C ++ คืออะไร

(โปรดทราบว่าฉันไม่ชอบการนำมรดกไปใช้โดยทั่วไปซึ่งอาจอธิบายได้มาก ... )

คำตอบ:


12

นี่คือตัวอย่าง

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

protected:
  ~Base() { }
};

ใช้เป็นคลาสพื้นฐานที่ไม่ใช่ polymorphic แต่ผู้ใช้จะไม่ได้รับอนุญาตให้โทรหาdelete baseptr;เพราะ destructor ไม่สามารถเข้าถึงได้ เนื่องจากมันไม่มีตัวทำลายเสมือนการอนุญาตให้คนทำเช่นนั้นจะเป็นพฤติกรรมที่ไม่ได้กำหนด ดูที่"Virtuality"โดย Herb


1
เกิดอะไรขึ้นกับพวกคุณ? ทำไมการลงคะแนนนี้ มันสมเหตุสมผลอย่างสมบูรณ์แบบ หากคุณไม่เข้าใจโปรดถาม หากคุณรู้สึกว่ามันผิดโปรดอธิบาย เรามาที่นี่เพื่อเรียนรู้จากข้อมูลเชิงลึกของคุณ
sbi

ทำไม -1 นี่เป็นสิ่งแรกที่ฉันคิด
GManNickG

1
Constructors and Destructors เกี่ยวกับการใช้งานที่ฉันเห็น โปรดทราบว่า gcc ยังคงส่งสัญญาณเตือนว่า destructor นั้นไม่ใช่แบบเสมือนจริงในอันนี้
Matthieu M.

+1 ฉันยังใช้วิธีการที่ได้รับการป้องกันในการใช้คำแนะนำหนังสือบางเล่ม: มีส่วนต่อประสานสาธารณะที่มีฟังก์ชันเสมือนที่ได้รับการป้องกันแทนที่จะเป็นฟังก์ชันเสมือนสาธารณะ
Klaim

3

ตัวอย่างหนึ่งที่ฉันใช้บ่อยคือในคลาสฐานของลำดับชั้นวัตถุของฉันฉันจะมี Logger ที่ได้รับการป้องกัน คลาสพื้นฐานทั้งหมดของฉันจะต้องเข้าถึง Logger แต่ไม่มีเหตุผลที่จะทำให้เข้าถึงได้แบบสาธารณะ

นอกจากนี้หากคุณใช้รูปแบบเทมเพลตและคุณมีวิธีเรียกใช้งานก่อนหน้าหรือโพสต์บนชั้นฐานคุณอาจต้องการเรียกใช้งานฐานจากวิธีการแทนที่ หากฐานเป็นส่วนตัวเท่านั้น (และยังสามารถเขียนทับใน C ++) คุณจะไม่สามารถเรียกใช้งานฐานได้จากวิธีการแทนที่


1
เทมเพลตรูปแบบทั้งหมดเกี่ยวกับการไม่ต้องเรียกวิธีการเรียนพื้นฐานหรือไม่?
sbi

ชี้ไปที่ แต่ฉันจะไม่บอกว่ามัน 'ทั้งหมด' เกี่ยวกับการไม่ต้องเรียกวิธีการเรียนฐาน ในหลาย ๆ สถานการณ์ฉันมีลำดับชั้นวัตถุที่ใช้รูปแบบเทมเพลตที่มีหลายระดับซึ่งแต่ละอันเพิ่มการทำงาน / การตรวจสอบเพิ่มขึ้นเล็กน้อย ในกรณีเหล่านี้จำเป็นต้องใช้วิธีการป้องกัน
bryanatkinson

1

แค่ตัวอย่างที่ฉันเคยใช้ในอดีต วิธีการที่ได้รับการป้องกันนั้นยอดเยี่ยมสำหรับการจัดทำฟังก์ชั่นการใช้งานเฉพาะขณะเดียวกันก็ช่วยให้ชั้นฐานสามารถติดตามสิ่งต่างๆ พิจารณาคลาสพื้นฐานที่จัดเตรียมฟังก์ชันการเตรียมข้อมูลเบื้องต้น overridable แต่ต้องมีสถานะเพื่อพิจารณาว่าการเตรียมใช้งาน:

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

ทุกอย่างดีและดีที่นี่ ยกเว้นเมื่อคลาสที่ได้รับไม่รบกวนการโทรsetInitialized()ไม่น้อยความจริงที่ว่าทุกคนสามารถเรียกมันได้ (เราสามารถทำให้การป้องกันนี้ที่นี่และอีกเหตุผลที่จะใช้วิธีการป้องกัน!) ฉันชอบคลาสที่ใช้ประโยชน์จากสมาชิกที่ได้รับการปกป้องเสมือน:

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

ในคลาสใหม่ของเราการกำหนดค่าเริ่มต้นทั้งหมดยังคงมอบให้กับคลาสที่ได้รับ มีข้อยกเว้นตามที่ถูกโยนเรารักษาสัญญา "ชั้นนี้เริ่มต้นได้" ที่วิธีการของเราบอกว่าจะเกิดขึ้น


0

คุณสมบัติอื่น ๆ ที่protectedช่วยให้คุณแยกการห่อหุ้มเพื่อขยายบางส่วน การทำลายแนวคิด OO ที่บริสุทธิ์มักทำด้วยเหตุผลหลายประการ

  1. บรรลุประสิทธิภาพที่ดีขึ้น (คิด inline )
  2. การทำโค้ดให้เข้าใจง่ายและแดกดัน
  3. การห่อหุ้มที่ดีขึ้น ( friendช่วยให้คุณสามารถ จำกัด การเข้าถึงสมาชิกชั้นเรียนให้กับเพื่อนไม่กี่คน)

และ protectedเป็นเพียงหนึ่งในเครื่องมือในกล่องนั้น คุณสามารถใช้มันหากคุณต้องการให้คลาสที่ได้รับเข้าถึงบางส่วนของคลาสที่ควรถูกซ่อนจากสาธารณะทั่วไป

กรณีหนึ่งที่ฉันใช้มันคือการสร้างคอนสตรัคเตอร์ทั้งหมดของคลาสprotectedโดยพื้นฐานแล้วทำให้คลาสนั้นเป็นนามธรรม (คุณไม่สามารถสร้างอินสแตนซ์ของมันได้


0

บางทีมันอาจจะเป็นการออกแบบที่ไม่ดี แต่ฉันมีมันสำหรับสิ่งนี้

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

ชั้นเรียนมาในอาจก่อให้เกิดสัญญาณโดยการเรียกupdate() trigger_signal()แต่เนื่องจากนั่นคือทั้งหมดที่พวกเขาควรจะสามารถทำกับสัญญาณได้สัญญาณจึงถูกปล่อยให้เป็นส่วนตัว ฟังก์ชั่นทริกเกอร์ได้รับการป้องกันเพราะคลาสที่ได้รับควรจะสามารถทริกเกอร์มันได้ไม่ใช่สิ่งใดเลย


0

"วิธีการสาธารณะ": คลาสสามารถทำได้ "วิธีการป้องกัน": วิธีการเรียนสามารถทำเช่นนี้ "วิธีการส่วนตัว": ชั้นเรียนทำได้อย่างไร แต่ "ฉันหวาดระแวงและไม่ต้องการให้ใครรู้ว่าฉันทำได้อย่างไร"

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

ดังนั้นนักปรุงอาหาร (นักพัฒนา) คนใหม่ก็มาถึงร้านอาหารฟาสต์ฟู้ดของคุณ คุณสอนคุณขายเบอร์เกอร์ (วิธีสาธารณะ) วิธีเตรียมเบอร์เกอร์ (วิธีการป้องกัน) แต่ให้ซอสสูตรลับที่จดสิทธิบัตรไว้กับตัวเอง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.