程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++基礎知識 >> C++繼承權限和繼承方式

C++繼承權限和繼承方式

編輯:C++基礎知識
C++繼承的一般語法為:

class 派生類名:[繼承方式] 基類名{
    派生類新增加的成員
};

繼承方式限定了基類成員在派生類中的訪問權限,包括 public(公有的)、private(私有的)和 protected(受保護的)。此項是可選項,如果不寫,默認為 private(成員變量和成員函數默認也是 private)。

現在我們知道,public、protected、private 三個關鍵字除了可以修飾類的成員,還可以指定繼承方式。

public、protected、private 修飾類的成員

類成員的訪問權限由高到低依次為 public --> protected --> private,我們在《C++類成員的訪問權限》一節中講解了 public 和 private:public 成員可以通過對象來訪問,private 成員不能通過對象訪問。

現在再來補充一下 protected。protected 成員和 private 成員類似,也不能通過對象訪問。但是當存在繼承關系時,protected 和 private 就不一樣了:基類中的 protected 成員可以在派生類中使用,而基類中的 private 成員不能在派生類中使用,下面是詳細講解。

public、protected、private 指定繼承方式

不同的繼承方式會影響基類成員在派生類中的訪問權限。

1) public繼承方式
  • 基類中所有 public 成員在派生類中為 public 屬性;
  • 基類中所有 protected 成員在派生類中為 protected 屬性;
  • 基類中所有 private 成員在派生類中不能使用。

2) protected繼承方式
  • 基類中的所有 public 成員在派生類中為 protected 屬性;
  • 基類中的所有 protected 成員在派生類中為 protected 屬性;
  • 基類中的所有 private 成員在派生類中不能使用。

3) private繼承方式
  • 基類中的所有 public 成員在派生類中均為 private 屬性;
  • 基類中的所有 protected 成員在派生類中均為 private 屬性;
  • 基類中的所有 private 成員在派生類中不能使用。

通過上面的分析可以發現:
1) 基類成員在派生類中的訪問權限不得高於繼承方式中指定的權限。例如,當繼承方式為 protected 時,那麼基類成員在派生類中的訪問權限最高也為 protected,高於 protected 的會降級為 protected,但低於 protected 不會升級。再如,當繼承方式為 public 時,那麼基類成員在派生類中的訪問權限將保持不變。

也就是說,繼承方式中的 public、protected、private 是用來指明基類成員在派生類中的最高訪問權限的。

2) 不管繼承方式如何,基類中的 private 成員在派生類中始終不能使用(不能在派生類的成員函數中訪問或調用)。

3) 如果希望基類的成員能夠被派生類繼承並且毫無障礙地使用,那麼這些成員只能聲明為 public 或 protected;只有那些不希望在派生類中使用的成員才聲明為 private。

4) 如果希望基類的成員既不向外暴露(不能通過對象訪問),還能在派生類中使用,那麼只能聲明為 protected。

注意,我們這裡說的是基類的 private 成員不能在派生類中使用,並沒有說基類的 private 成員不能被繼承。實際上,基類的 private 成員是能夠被繼承的,並且(成員變量)會占用派生類對象的內存,它只是在派生類中不可見,導致無法使用罷了。private 成員的這種特性,能夠很好的對派生類隱藏基類的實現,以體現面向對象的封裝性。

下表匯總了不同繼承方式對不同屬性的成員的影響結果 繼承方式/基類成員 public成員 protected成員 private成員 public繼承 public protected 不可見 protected繼承 protected protected 不可見 private繼承 private private 不可見
由於 private 和 protected 繼承方式會改變基類成員在派生類中的訪問權限,導致繼承關系復雜,所以實際開發中我們一般使用 public。

【示例】演示類的繼承關系。
#include<iostream>
using namespace std;

//基類People
class People{
public:
    void setname(char *name);
    void setage(int age);
    void sethobby(char *hobby);
    char *gethobby();
protected:
    char *m_name;
    int m_age;
private:
    char *m_hobby;
};
void People::setname(char *name){ m_name = name; }
void People::setage(int age){ m_age = age; }
void People::sethobby(char *hobby){ m_hobby = hobby; }
char *People::gethobby(){ return m_hobby; }

//派生類Student
class Student: public People{
public:
    void setscore(float score);
protected:
    float m_score;
};
void Student::setscore(float score){ m_score = score; }

//派生類Pupil
class Pupil: public Student{
public:
    void setranking(int ranking);
    void display();
private:
    int m_ranking;
};
void Pupil::setranking(int ranking){ m_ranking = ranking; }
void Pupil::display(){
    cout<<m_name<<"的年齡是"<<m_age<<",考試成績為"<<m_score<<"分,班級排名第"<<m_ranking<<",TA喜歡"<<gethobby()<<"。"<<endl;
}

int main(){
    Pupil pup;
    pup.setname("小明");
    pup.setage(15);
    pup.setscore(92.5f);
    pup.setranking(4);
    pup.sethobby("乒乓球");
    pup.display();

    return 0;
}
運行結果:
小明的年齡是15,考試成績為92.5分,班級排名第4,TA喜歡乒乓球。

這是一個多級繼承的例子,Student 繼承自 People,Pupil 又繼承自 Student,它們的繼承關系為 People --> Student --> Pupil。Pupil 是最終的派生類,它擁有基類的 m_name、m_age、m_score、m_hobby 成員變量以及 setname()、setage()、sethobby()、gethobby()、setscore() 成員函數。

注意,在派生類 Pupil 的成員函數 display() 中,我們借助基類的 public 成員函數 gethobby() 來訪問基類的 private 成員變量 m_bobby,因為 m_hobby 是 private 屬性的,在派生類中不可見,所以只能借助基類的 public 成員函數 sethobby()、gethobby() 來訪問。

在派生類中訪問基類 private 成員的唯一方法就是借助基類的非 private 成員函數,如果基類沒有非 private 成員函數,那麼該成員在派生類中將無法訪問(除非使用下面講到的 using 關鍵字)。

改變訪問權限

使用 using 關鍵字可以改變基類成員在派生類中的訪問權限,例如將 public 改為 private、將 private 改為 public。

using 關鍵字使用示例:
#include<iostream>
using namespace std;

//基類People
class People{
public:
    void show();
protected:
    char *m_name;
    int m_age;
};
void People::show(){
    cout<<m_name<<"的年齡是"<<m_age<<endl;
}

//派生類Student
class Student: public People{
public:
    void learning();
public:
    using People::m_name;  //將private改為public
    using People::m_age;  //將private改為public
    float m_score;
private:
    using People::show;  //將public改為private
};
void Student::learning(){
    cout<<"我是"<<m_name<<",今年"<<m_age<<"歲,這次考了"<<m_score<<"分!"<<endl;
}

int main(){
    Student stu;
    stu.m_name = "小明";
    stu.m_age = 16;
    stu.m_score = 99.5f;
    stu.show();  //compile error
    stu.learning();

    return 0;
}
代碼中首先定義了基類 People,它包含兩個 protected 屬性的成員變量和一個 public 屬性的成員函數。定義 Student 類時采用 public 繼承方式,People 類中的成員在 Student 類中的訪問權限默認是不變的。

不過,我們使用 using 改變了它們的默認訪問權限,如代碼第16~20行所示,將 say() 函數修改為 private 屬性的,是降低訪問權限,將 name、age 變量修改為 public 屬性的,是提高訪問權限。

因為 say() 函數是 private 屬性的,所以代碼第33行會報錯。把該行注釋掉,程序輸出結果為:
我是小明,今年16歲,這次考了99.5分!
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved