C++ 派生類成員的訪問屬性


派生類成員的訪問屬性:

C++繼承方式總共分為以下幾種:public、private、protected三種(它們直接影響到派生類的成員、及其對象對基類成員訪問的規則)。
(1)public(公有繼承):繼承時保持基類中各成員屬性不變,並且基類中private成員被隱藏。派生類的成員只能訪問基類中的public/protected成員,而不能訪問private成員;派生類的對象只能訪問基類中的public成員。
(2)private(私有繼承):繼承時基類中各成員屬性均變為private,並且基類中private成員被隱藏。派生類的成員也只能訪問基類中的public/protected成員,而不能訪問private成員;派生類的對象不能訪問基類中的任何的成員。
(3)protected(保護性繼承):繼承時基類中各成員屬性均變為protected,並且基類中private成員被隱藏。派生類的成員只能訪問基類中的public/protected成員,而不能訪問private成員;派生類的對象不能訪問基類中的任何的成員。


 

由上表可知:

public繼承:不改變基類成員的訪問控制。
private繼承:派生類所繼承的基類成員的訪問控制都變為private。
protected繼承:基類中的private成員的訪問控制不變,其余的都變為protected。
基類的 public成員被派生類繼承,且在派生類中是可見的(visible in the derived class)。
基類的 private成員被派生類繼承,但在派生類中是不可見的(not visible in the derived class)。

受保護成員 protected Members

以下面兩個例子來說明受保護成員的可見性。

class BC { public: void set_x( int a ) { x = a; } protected: int get_x( ) const { return x; } private: int x; }; class DC : public BC { public: void add2() { int c=get_x();//可以執行 set_x(c+2);//可以執行  } } void g() { DC d; d.get_x( );//在客戶代碼中不可見,不能夠執行 }

 

class BC { protected: int get_w( ) const; //…… }; class DC : public BC { public: int get_val( ) const { return get_w( );//派生類中可見,可以執行  } void base_w( const BC& b ) const { cout << b.get_w( ) << endl;//客戶代碼中不可見,不能夠執行  } };

 

保護成員是專為繼承機制而設的。
受保護成員(A protected member)僅在自己的類和其派生類中是可見的。


繼承方式不會影響基類成員在派生類中的能見度。

名字隱藏 Name hiding

 如果在派生類中添加了成員(數據、函數),其與基類的成員重名,本地成員(the local member)隱藏繼承來的成員 ( hides the inherited member)。

以下面的代碼為例:

class BC {
  public:
    void h( float );
};

class DC : public BC {
  public:
    void h( char[ ] );
};

DC繼承自BC,其中BC含有void h(float)函數,DC中含有void h(char[])函數,這兩個函數的簽名不同,那么是否能夠構成函數的重載呢?

對於下面的兩行代碼都能夠執行?

void  f ( )
{ 
    DC d1;
    d1.h( "Boffo!" );//可以執行
    d1.h( 707.7 );//不可以執行
}

其實這種想法是不對的,重載必須是同一級的函數才能構成,而這兩個函數的級別是不一致的,本地成員void h(char[])將會隱藏繼承來的成員 void h(float)!!

void  f ( )
{ 
    DC d1;
    d1.BC::h( 707.7 );//這樣寫是可以的
}

 

再就一個例子

對於一個實現數組升序的類繼承自一個數組類。

class Array
{
public:
    void insert(int X)
    {
        將X插入到 last_pos  指定的位置;
        last_pos++;
    }
private:
    int  last_pos;
    //……
};
class AscArray : public Array
{
public:
    void insert( int X )
    {
        確定插入的位置,並將X插入
        // ...
    }
    // ...
};

其調用函數如下調用語法是正確的,但是其內涵錯誤

void  f (AscArray& as )
{
    as.insert( 10 );//正確,排序數組類中插入10然后實現排序
    as.Array::insert(10);//不正確,使用了數組類的插入方法,將10插入到了數組尾部,並不能實現排序功能

}

調整可訪問性 Adjusting access

一個繼承成員的訪問控制可能通過使用using聲明( using declaration)改變。
還是上面那個例子。

class AscArray : public Array 
{
  private:
    using Array::insert;
    //將基類的public成員的外部訪問權降低,使得無法通過派生類對象訪問該成員!
  public:
    void insert( int X ) { 
      確定插入的位置,並將X插入
      // ...
    }
  // ...
};
void  f(AscArray& as )
{
    as.insert( 10 );//正確
    as.Array::insert(10);//運行錯誤
}

在使用using聲明時,基類中公有的成員在公共派生類中必須是公有的,只有這樣才能保證公有繼承時“派生類對象是一個基類對象”的邏輯關系。

在基類中的private成員,不能在派生類中任何地方用using聲明。

同時,在基類中的protected成員,可在public派生下通過using聲明改為public成員。

 

#include <iostream>
using namespace std;
class A
{
protected:
    void PrintA( )
    {
        cout << "A::Print"<<endl ;
    }
};
class B: public A
{
public:
    using A::PrintA;//改為公有
public:
    void PrintB( )
    {
        cout << "B::Print" <<endl;
    }
};
int main( )
{
    A a;
    B b;
    b.PrintB( );
    b.PrintA( );
    return 0;
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM