簡體   English   中英

什么是訪問說明符? 我應該繼承私人,受保護的還是公開的?

[英]What are access specifiers? Should I inherit with private, protected or public?

我對訪問修飾符在繼承方面的含義感到困惑。 涉及privateprotectedpublic關鍵字的繼承之間有什么區別?

什么是訪問說明符?

C ++中的class / struct / Union有3個access specifiers 這些訪問說明符定義了如何訪問類的成員。 當然,類的任何成員都可以在該類中訪問(在同一類的任何成員函數內)。 繼續介紹訪問說明符的類型,它們是:

公共 -可以通過類的對象從類外部訪問聲明為“公共”的成員。

受保護的 -聲明為受保護的成員只能從類BUT外部訪問, 只能從該類派生。

私人 -這些成員只能在班級內部訪問。 不允許外部訪問。

源代碼示例:

class MyClass
{
    public:
        int a;
    protected:
        int b;
    private:
        int c;
};

int main()
{
    MyClass obj;
    obj.a = 10;     //Allowed
    obj.b = 20;     //Not Allowed, gives compiler error
    obj.c = 30;     //Not Allowed, gives compiler error
}

繼承和訪問說明符

C ++中的繼承可以是下列類型之一:

  • Private繼承
  • Public繼承
  • Protected繼承

以下是與每個規則有關的成員訪問規則:

第一條也是最重要的規則除同一個類的成員外,從任何地方都無法訪問該類的Private成員。

公共繼承:

基類的所有Public成員將成為派生類的Public成員,並且
基本類的所有Protected成員都將成為派生類的Protected成員。

即,成員的訪問權限沒有變化。 我們之前討論的訪問規則將進一步應用於這些成員。

代碼示例:

Class Base
{
    public:
        int a;
    protected:
        int b;
    private:
        int c;
};

class Derived:public Base
{
    void doSomething()
    {
        a = 10;  //Allowed 
        b = 20;  //Allowed
        c = 30;  //Not Allowed, Compiler Error
    }
};

int main()
{
    Derived obj;
    obj.a = 10;  //Allowed
    obj.b = 20;  //Not Allowed, Compiler Error
    obj.c = 30;  //Not Allowed, Compiler Error

}

私有繼承:

所有基礎類的Public成員都將成為派生類的Private成員,
基本類的所有Protected成員都將成為派生類的Private成員。

一個代碼示例:

Class Base
{
    public:
      int a;
    protected:
      int b;
    private:
      int c;
};

class Derived:private Base   //Not mentioning private is OK because for classes it  defaults to private 
{
    void doSomething()
    {
        a = 10;  //Allowed 
        b = 20;  //Allowed
        c = 30;  //Not Allowed, Compiler Error
    }
};

class Derived2:public Derived
{
    void doSomethingMore()
    {
        a = 10;  //Not Allowed, Compiler Error, a is private member of Derived now
        b = 20;  //Not Allowed, Compiler Error, b is private member of Derived now
        c = 30;  //Not Allowed, Compiler Error
    }
};

int main()
{
    Derived obj;
    obj.a = 10;  //Not Allowed, Compiler Error
    obj.b = 20;  //Not Allowed, Compiler Error
    obj.c = 30;  //Not Allowed, Compiler Error

}

受保護的繼承:

所有基類的Public成員均成為派生類的Protected成員,並且
基本類的所有Protected成員都將成為派生類的Protected成員。

代碼示例:

Class Base
{
    public:
        int a;
    protected:
        int b;
    private:
        int c;
};

class Derived:protected Base  
{
    void doSomething()
    {
        a = 10;  //Allowed 
        b = 20;  //Allowed
        c = 30;  //Not Allowed, Compiler Error
    }
};

class Derived2:public Derived
{
    void doSomethingMore()
    {
        a = 10;  //Allowed, a is protected member inside Derived & Derived2 is public derivation from Derived, a is now protected member of Derived2
        b = 20;  //Allowed, b is protected member inside Derived & Derived2 is public derivation from Derived, b is now protected member of Derived2
        c = 30;  //Not Allowed, Compiler Error
    }
};

int main()
{
    Derived obj;
    obj.a = 10;  //Not Allowed, Compiler Error
    obj.b = 20;  //Not Allowed, Compiler Error
    obj.c = 30;  //Not Allowed, Compiler Error
}

請記住,相同的訪問規則適用於繼承層次結構中的類和成員。


注意事項:

-訪問規范是按類而不是按對象的

請注意,訪問規范C ++是按類而不是按對象工作的。
一個很好的例子是,在復制構造函數或“復制分配”運算符函數中,可以訪問正在傳遞的對象的所有成員。

-派生類只能訪問其自己的基類的成員

考慮以下代碼示例

class Myclass
{ 
    protected: 
       int x; 
}; 

class derived : public Myclass
{
    public: 
        void f( Myclass& obj ) 
        { 
            obj.x = 5; 
        } 
};

int main()
{
    return 0;
}

它給出了一個編譯錯誤:

prog.cpp:4:錯誤:“ int Myclass :: x”受到保護

因為派生類只能訪問其自己的基類的成員。 請注意,此處傳遞的對象obj與訪問它的derived類函數沒有任何關系,它是一個完全不同的對象,因此derived成員函數無法訪問其成員。


什么是friend friend如何影響訪問規范規則?

您可以將一個函數或類聲明為另一個類的friend 這樣做時,訪問規范規則不適用於friend類/函數。 該類或函數可以訪問該特定類的所有成員。

friend的包裝破裂了嗎?

不,他們沒有,相反,它們增強了封裝!

friend飛船用於表示兩個實體之間的故意強耦合
如果兩個實體之間存在特殊關系,使得一個實體需要訪問其他privateprotected成員,但是您不希望每個人都可以使用public訪問說明符進行訪問,則應該使用friend

Scott Meyers在Effective C ++中的解釋可能有助於理解何時使用它們:

公共繼承應為“是一個關系”建模,而私有繼承應為“按條件實現”模型-因此,您不必遵循超類的接口,而只是在重用實施。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM