C++中public,protected,private派生類繼承問題和訪問權限問題
當一個子類從父類繼承時,父類的所有成員成為子類的成員,此時對父類成員的訪問狀態由繼承時使用的繼承限定符決定。
1.如果子類從父類繼承時使用的繼承限定符是public,那么
(1)父類的public成員成為子類的public成員,允許類以外的代碼訪問這些成員;
(2)父類的private成員仍舊是父類的private成員,子類成員不可以訪問這些成員;
(3)父類的protected成員成為子類的protected成員,只允許子類成員訪問;
2.如果子類從父類繼承時使用的繼承限定符是protected,那么
(1)父類的public成員成為子類的protected成員,只允許子類成員訪問;
(2)父類的private成員仍舊是父類的private成員,子類成員不可以訪問這些成員;
(3)父類的public成員成為子類的protected成員,只允許子類成員訪問
3.如果子類從父類繼承時使用的繼承限定符是private,那么
(1)父類的public成員成為子類的private成員,只允許子類成員訪問;
(2)父類的private成員仍舊是父類的private成員,子類成員不可以訪問這些成員;
(3)父類的protected成員成為子類的private成員,只允許子類成員訪問;
其實這些都很有的規律的,子類public時表示最大的繼承權限是public,所以子類按照原樣繼承,子類protected繼承時最大繼承權限是protected, 所以基類的public成員降級成為protected了....子類private繼承時所以都成為private了, 不過子類不能訪問基類的private成員..
子類默認的是private繼承基類...
舉個使用private繼承的例子,Boost::Utility庫的不可以復制的類 noncopyable
#include "boost/utility.hpp"
或者是
#include "boost/noncopyable.hpp"
- #ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
- #define BOOST_NONCOPYABLE_HPP_INCLUDED
- namespace boost {
- // Private copy constructor and copy assignment ensure classes derived from
- // class noncopyable cannot be copied.
- // Contributed by Dave Abrahams
- namespace noncopyable_ // protection from unintended ADL
- {
- class noncopyable
- {
- protected:
- noncopyable() {}
- ~noncopyable() {}
- private: // emphasize the following members are private
- noncopyable( const noncopyable& );
- const noncopyable& operator=( const noncopyable& );
- };
- }
- typedef noncopyable_::noncopyable noncopyable;
- } // namespace boost
- #endif // BOOST_NONCOPYABLE_HPP_INCLUDED
類 boost::noncopyable 被規定為作為私有基類來使用,它可以有效地關閉復制構造和賦值操作:
- #include "boost/utility.hpp"
- class please_dont_make_copies : boost::noncopyable {
- public:
- void do_stuff() {
- std::cout << "Dear client, you just cannot copy me!";
- }
- };
這樣就禁止了復制和賦值....
=========================================================================
三法則(英語:rule of three,the Law of The Big Three,The Big Three;三法則,三大定律)在 C++ 程序設計里,它是一個以設計的基本原則而制定的定律,三法則的要求在於,假如類型有明顯地定義下列其中一個成員函數,那么程序員必須連其他二個成員函數也一同編寫至類型內,亦即下列三個成員函數缺一不可。 [1]:
上述三個函數是特別的成員函數,假如程序員沒有自行定義或是編寫聲明它們,那么編譯器會自動地創建它們,並且會編譯至應用程序內。相反地,假如程序員有定義上述三者其中一個函數,那么由編譯器自動產生出來的上述三個函數是不會搭配到這個類型內。三法則(Rule of three)這個專有名詞是由 Marshall Cline 於 1991 年創立的[2]。
class_a.h文件
- #ifndef _CLASS_A_H_
- #define _CLASS_A_H_
- #ifndef _MSC_VER
- #undef NULL
- #define NULL 0
- #endif
- #include <iostream>
- #include <cstdlib>
- #define BUFFER_SIZE 7
- using namespace std;
- class ClassA
- {
- public:
- // 三種建構子
- ClassA()
- {
- cout<<"ClassA():"<<endl;
- this->setAlloc(BUFFER_SIZE);
- this->setData();
- }
- ClassA(const int n)
- {
- cout<<"ClassA(const int n):"<<endl;
- this->setAlloc(n);
- this->setData();
- }
- // 複製建構子
- ClassA(const ClassA& clone)
- {
- cout<<"ClassA(const ClassA& clone):"<<endl;
- this->setAlloc(clone.m_N);
- this->setData(clone.m_pn);
- }
- // 複製指定運算子成員函式
- ClassA& operator=(const ClassA& clone)
- {
- cout<<"ClassA& operator=(const ClassA& clone)"<<endl;
- // 保護:禁止自己設值給自己
- if ( this != &clone )
- {
- this->setData(clone.m_pn);
- }
- return *this;
- }
- // 解構子
- ~ClassA()
- {
- cout<<"~Destructor!!!"<<endl;
- // 釋放記憶體
- delete [] this->m_pn;
- }
- // 配置
- void setAlloc(const int n)
- {
- this->m_N = n;
- // 配置一塊記憶體給指標
- this->m_pn = new int[this->m_N];
- }
- // 填入一堆的整數值
- void setData(int* pn = NULL)
- {
- for ( int i = 0; i < this->m_N; i ++)
- {
- // 給初始值
- if ( pn == NULL )
- {
- this->m_pn[i] = (2 * i + 1);
- }
- // 複製指標儲存的整數值
- else
- {
- this->m_pn[i] = pn[i];
- }
- }
- }
- // 列印顯示
- void print(void)
- {
- for ( int i = 0; i < this->m_N; i ++)
- {
- cout<<" "<<this->m_pn[i];
- }
- cout<<endl;
- }
- private:
- // 指標
- int* m_pn;
- // 元素個數
- int m_N;
- };
- #endif
主函數
- // Headers and Macros
- #ifndef _MSC_VER
- #undef NULL
- #define NULL 0
- #endif
- #include <iostream>
- #include <cstdlib>
- #include "class_a.h"
- using namespace std;
- //
- //Main Function
- #ifndef _MSC_VER
- int
- #else
- void
- #endif
- main(int argc, char** argv)
- {
- // 區塊
- {
- // 建立第一個物件
- ClassA A(BUFFER_SIZE);
- cout<<" A =>";
- A.print();
- {
- // 開始執行 ClassA(const ClassA& clone)
- ClassA B = A;
- cout<<" B =>";
- B.print();
- }
- {
- ClassA C;
- // 開始執行 ClassA& operator=(const ClassA& clone)
- C = A;
- cout<<" C =>";
- C.print();
- }
- }
- system("PAUSE");
- return
- #ifndef _MSC_VER
- EXIT_SUCCESS
- #endif
- ;
- }