回顧C++:訪問權限控制之 公有、保護、私有繼承用法詳解與總結

理解

  • 類的成員的訪問控制說明符:主要用於控制派生類成員對基類成員的訪問權限
  • 類的派生訪問說明符:主要用於控制派生類實例對基類的成員訪問權限
  • 公有繼承 -> 保護繼承 -> 私有繼承, 派生類實例對基類成員的訪問權限束縛依次加強。除公有繼承外,保護繼承相當於重置基類公有成員爲保護成員,私有繼承相當於重置基類公有成員和保護成員爲私有成員。

主要用法

1. 阻斷當前類實例對父類所有成員的訪問權限

class Per {
  public:
    Per() = default;
    int pubPer = 1;
  protected:
    int protPer = 1;
  private:
    int prvPer = 1;
};

class Stu: protected Per {
  public:
    Stu() = default;
    int pubStu = 1;
  protected:
    int protStu = 1;
  private:
    int priStu = 1;
};

class Monitor: public Stu {
  public:
    Monitor() = default;
    int pubMonitor = 1;
  protected:
    int protMonitor = 1;
  private:
    int priMonitor = 1;
};
int main () {
  Stu s;
  Monitor m;
  s.pubPer++; // error line
  s.protPer++; // error line
  m.pubPer++; // error line
  m.protPer++; // error line
  return 0;
}

當 保持Monitor公有繼承於Stu 時:
若 Stu 保護繼承於 Per, 則 Stu中對 Per中的公有成員訪問權限被重置爲protected,即 Stu 的實例不能再訪問 Per 中的公有成員, 也就是Stu實例無法訪問Per中的任何成員,Monitot實例也一樣無法訪問。 同理,若Stu 私有繼承於 Per 也能實現相似的限制效果。即阻斷Stu類向下(包括Stu)的所有類的實例對基類所有成員的訪問。

2. 實現用法1的效果的同時,阻斷派生類的派生類成員對基類所有成員的訪問

class Per {
  public:
    Per() = default;
    int pubPer = 1;
  protected:
    int protPer = 1;
  private:
    int prvPer = 1;
};

class Stu: private Per {
  public:
    Stu() = default;
    int pubStu = 1;
  protected:
    int protStu = 1;
  private:
    int priStu = 1;
};

class Monitor: public Stu {
  public:
    Monitor() = default;
    int pubMonitor = 1;
    void watch () {
      pubPer++;  // error line
    }
  protected:
    int protMonitor = 1;
  private:
    int priMonitor = 1;
};


int main () {
  Stu s;
  Monitor m;
  s.pubPer++; // error line
  s.protPer++; // error line
  m.pubPer++; // error line
  m.protPer++; // error line
  return 0;
}

3. 限制派生類類型 到 基類類型的轉換

class Per {
  public:
    Per() = default;
};

class Stu: protected Per {
  public:
    Stu() = default;
};

int main () {
  Stu s;
  Per p = s; // error line
  return 0;
}

4. 實現用法3的效果的同時,限制派生類的派生類及其友元 實現 派生類類型 向 基類類型的轉換

即對某個特定作用域來說,如若基類中的公有成員可訪問,則能夠實現派生類類型到基類類型的轉換。

class Per {
  public:
    Per() = default;
    void eat () {}
};

class Stu: private Per {
  public:
    Stu() = default;
    void test () {
      Per p = *this;
    }
  private:
    Stu *thisS;
};

class Monitor: public Stu {
  public:
    void test () {
      Stu s;
      Per p = s; // error line
    }
};

int main () {
  Stu s;
  Per p = s; // error line
  return 0;
}

通過派生訪問說明符與成員訪問說明符的配合,可以更加全面地實現各種應用場景。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章