C++類的繼承與多重繼承的訪問控制
對於單個類來說,討論保護繼承與私有繼承的區別意義是不大的,他們的區別只在多級繼承的情況中體現。
在這裡我宣告一下,對於此章節的內容不太適合用過多的文字進行描述,主要還是看例子,通過例子熟悉之間的關係,過多的文字描述會模糊讀者思路。
例程如下(重要部分都做了詳細說明):
//程式作者:管寧
//站點:www.cndev-lab.com
//所有稿件均有版權,如要轉載,請務必著名出處和作者
#include <iostream>
using namespace std;
class Base
{
public://公有的
int a1;
virtual void test() = 0;
protected://受保護的
int a2;
private://私有的
int a3;
};
//------------------------------------------------------------------------------
class ProtectedClass:protected Base//保護繼承
{
public:
void test()
{
a1 = 1;//a1在這裡被轉變為protected
a2 = 2;//a2在這裡被轉變為protected
//a3=3;//錯誤,派生類不能訪問基類的私有成員
}
};
class ControlProtectedClass:public ProtectedClass//以public方式繼承ProtectedClass類
{
public:
void test()
{
a1 = 1;//a1在這裡仍然保持為a1在這裡被轉變為protected
a2 = 2;//a2在這裡仍然保持為a1在這裡被轉變為protected
//a3=3;//錯誤,由於Base類成員為私有的,即使是上級父類是保護繼承,也不能改變Base類成員的控制型別
}
};
//------------------------------------------------------------------------------
class PrivateClass:private Base//私有繼承
{
public:
void test()
{
a1 = 1;//a1在這裡被轉變為private
a2 = 2;//a2在這裡被轉變為private
//a3=3;//錯誤,基類私有成員對檔案區域與派生類區域都是不可訪問的
}
};
class ControlPrivateClass:public PrivateClass//以public方式繼承PrivateClass類
{
public:
void test()
{
//a1=1;//錯誤,由於基類PrivateClass為私有繼承,a1已經轉變為private
//a2=2;//錯誤,由於基類PrivateClass為私有繼承,a1已經轉變為private
//a3=3;//錯誤,由於Base類成員為私有的,PrivateClass類也為私有繼承
}
};
//------------------------------------------------------------------------------
class PublicClass:public Base//共有繼承有區別與其它方式的繼承,繼承後的各成員不會其改變控制方式
{
public:
void test()
{
a1 = 1;//a1仍然保持public
a2 = 2;//a2仍然保持protected
//a3=3;//錯誤,派生類不能操作基類的私有成員
}
};
class ControlPublicClass:public PublicClass//以public方式繼承PublicClass類
{
public:
void test()
{
a1 = 1;//a1仍然保持public
a2 = 2;//a2仍然保持protected
//a3=3;//錯誤,由於Base類成員為私有成員,即使是上級父類是公有繼承,也不能改變Base類成員的控制型別
}
};
//------------------------------------------------------------------------------
int main()
{
system("pause");
}
認真看完了例子,相信細心的讀者對於共有繼承、保護繼承與私有繼承的區別與特點已經瞭解,最後再提醒一下讀者,在繼承關係中,基類的private成員不但對應用程式隱藏,即使是派生類也是隱藏不可訪問的,而基類的保護成員只對應用程式隱藏,對於派生類來說是不隱藏的,保護繼承與私有繼承在實際程式設計工作中使用是極其少見的,他們只在技術理論上有意義。
關於C++中protected的訪問許可權的討論已經是一個很陳舊的話題了,陳舊到大家都不願意去討論,覺得他見到到吃飯睡覺那麼自然。
我再次讀《C++ Primer》的時候,其中關於protected 成員的描述是這樣的:
protected Members
The protected access label can be thought of as a blend of private and public :
- Like private members, protected members are inaccessible to users of the class.
- Like public members, the protected members are accessible to classes derived from this class.
- In addition, protected has another important property:
A derived object may access the protected members of its base class only through a derived object. The derived class has no special access to the protected members of base type objects.
在沒有繼承的情況下,protected跟private相同。在派生類的時候才出現分化。
上面那段英文前兩條都很好理解,基類物件不能訪問基類的protected成員,派生類中可以訪問基類的protected成員。也就是說private成員是不能被繼承的,只有public,protected的成員才可以被繼承。
就是最後一條有些迷惑人,派生類物件如果要訪問基類protected成員只有通過派生類物件,派生類不能訪問基類物件的protected成員。
請注意 drived class和drived object:派生類和派生類物件。第一點和第二點都是針對派生類來說的。
對於第三點總結一句話:只有在派生類中才可以通過派生類物件訪問基類的protected成員。
舉一個簡單的例子:
- #include <iostream>
- usingnamespace std;
- class Base
- {
- public:
- Base(){};
- virtual ~Base(){};
- protected:
- int int_pro;
- };
- class A : public Base
- {
- public:
- A(){};
- A(int da){int_pro = da;}
- void Print(A &obj){obj.int_pro = 24;}
- void PrintPro(){cout << "The proteted data is " << int_pro <<endl;}
- };
- int main()
- {
- A aObj;
- A aObj2(5);
- aObj2.PrintPro();
- aObj.Print(aObj2);
- aObj2.PrintPro();
- //註釋1
- //aObj.int_pro = 8;
- }
編譯執行結果如下:
The protected data is 5
The protected data is 24
可見,在派生類內部直接訪問protected成員和訪問派生類物件基類的protected成員都是可行的。
但是若果解開註釋1.就會編譯報錯。
很多書上都說有派生類的情況下protected的訪問許可權同public。這種說法是不對的,類內部直接訪問沒什麼區別,但是訪問物件基類的protected成員只能是在該類的內部。
我這裡只列舉了只有一層繼承的情況,如果有多重繼承的情況,比如三層。那麼。中間層的類的內部還可以訪問第三層類物件的基類成員,但是不能訪問第三層類自己的protected的成員。
2009-01-23 20:40jackheroes8383 | 瀏覽 15825 次 C++
protected只能被類的成員函式和類的友元函式訪問 那子類能不能訪問啊? JAVA的protected是專門設計為讓子類訪問.
private也可以被類的成員函式和類的友元函式訪問 這個protected到底是為哪種情況設計的啊?
哈哈 protected專門就是為繼承(子類)設計的 用public繼承 那麼基類所有的訪問標識在子類不變 protected還是protected protected只有類本身 和類的子類可以訪問,物件是無法訪問的! 除了在繼承上 他跟private沒有任何區別! private 子類也將不能訪問! 跟你說了啊~~~ 只是在繼承上不同 其他都一樣的 private無法繼承 也就是說子類也不能用基類的 private... 但是protected就是可以的~ 明白嗎? pravite 只對本類可見 protected 對本類和繼承類可見
- 提問者評價
-
感謝
為您推薦:
<iframe src="http://entry.baidu.com/rp/home?di=u2115503&rsi0=450&rsi1=25&type=pageembed&version=1&titff=sans-serif%2Ctahoma%2C%22MicrosoftYaHei%22&titfs=14&rss2=%232d64b3&rss3=%232d64b3&title=C%2B%2B%3Aprotected%E8%AE%BF%E9%97%AE%E8%AF%B4%E6%98%8E%E7%AC%A6_%E7%99%BE%E5%BA%A6%E7%9F%A5%E9%81%93&ltu=http%3A%2F%2Fzhidao.baidu.com%2Fquestion%2F83373888.html%3Ffr%3Diks%26word%3DC%252B%252B%2Bprotected%26ie%3Dgbk&ref=http%3A%2F%2Fzhidao.baidu.com%2Fsearch%3Fct%3D17%26pn%3D0%26tn%3Dikaslist%26rn%3D10%26word%3DC%252B%252B%2520protected%26fr%3Dwwwt&pageWidth=1808&pageHeight=846&t=1442672803005&iframeWidth=1808&iframeHeight=846" align="center,center" marginwidth="0" marginheight="0" class="BAIDU_SS_HHIFRAME" scrolling="no" frameborder="0" allowtransparency="true" style="width: 450px; height: 25px; background-color: transparent;"></iframe>按預設排序 按時間排序其他1條回答
2009-01-23 20:48lostman250 六級有這麼一條原則:在繼承的時候,無論用什麼方式(public.protected.private),子類隨時都可以訪問父類的非private變數或函式。所以可以的!
看看這個例程就明白了:http://tech.163.com/05/0407/17/1GOJ25N500091589.html
軟體軟體開發程式語言專業回答 電子產品技術支援 技術部工程師 protected專門就是為繼承(子類)設計的 用public繼承,基類所有的訪問標識在子類不變, protected還是protected 。
C++程式設計思想中是這麼說的,public意味著隨後的定義對所有人都適用;private意味著除了該型別的建立者和該型別的內部成員函式之外,任何人都無法訪問這些定義;而protected是繼承的類可以訪問protected的成員,但不能訪問private的成員。本回答專業性由電腦網路分類達人 劉瑋認證
為您推薦:
<iframe src="http://entry.baidu.com/rp/home?di=u2115503&rsi0=450&rsi1=25&type=pageembed&version=1&titff=sans-serif%2Ctahoma%2C%22MicrosoftYaHei%22&titfs=14&rss2=%232d64b3&rss3=%232d64b3&title=C%2B%2B%E4%B8%AD%EF%BC%8C%E7%B1%BB%E7%9A%84protected%E7%A9%B6%E7%AB%9F%E6%9C%89%E4%BB%80%E4%B9%88%E4%BD%9C%E7%94%A8%EF%BC%9F_%E7%99%BE%E5%BA%A6%E7%9F%A5%E9%81%93&ltu=http%3A%2F%2Fzhidao.baidu.com%2Fquestion%2F574257523.html%3Ffr%3Diks%26word%3DC%252B%252B%2Bprotected%26ie%3Dgbk&ref=http%3A%2F%2Fzhidao.baidu.com%2Fsearch%3Fct%3D17%26pn%3D0%26tn%3Dikaslist%26rn%3D10%26word%3DC%252B%252B%2520protected%26fr%3Dwwwt&pageWidth=1808&pageHeight=846&t=1442673004018&iframeWidth=1808&iframeHeight=846" align="center,center" marginwidth="0" marginheight="0" class="BAIDU_SS_HHIFRAME" scrolling="no" frameborder="0" allowtransparency="true" style="width: 450px; height: 25px; background-color: transparent;"></iframe>錯了,不管何種繼承,基類的private成員派生類都無法訪問,當然也就出現了protected成員,集合了public成員(對派生類) 和 private成員(對外部訪問)的特點。追問:
子類不是可以呼叫基類public成員麼,然後public再呼叫private, 這樣不就呼叫了基類private了? 那基類怎樣訪問自己的protected呢追答:
呵呵,public直接呼叫private的話,所有外部訪問全部都能”訪問“private了,那private存在的意義是什麼? 基類自己的所有資料自己訪問是無限制的。 OOD的最大特點就是封裝和繼承,封裝也就是外界無法直接訪問private和protected成員,只給外界留出了public介面,藉由public介面來訪問private和proteced成員,用以限制外部訪問,就好像你只需要一個遙控器就能控制整個空調的開關,溫度的升降而不用去管其內部細節。 而protected存在的意義是當我不想向外部暴露某個函式或者成員變數,但是我又想讓派生類知道和訪問這個成員,就將其用protected標誌,就好比 你爹有兩筆存款,一筆是他養老用的,一筆是留給你買房的,養老用的這部分錢你肯定不能拿而且大概你也不知道有多少錢,但是給你買房用的你就可以隨便拿,如果你連養老用的這部分錢都拿了那你就是不肖子了,但是你爹可以隨便動給你買房的錢(因為錢是他賺的)。當然,不管是養老用的錢還是給你買房用的錢,外人都不能動而且也不知道。追問:
暈啊 您確定您說的是對的?剛剛有人說,子類是可以間接來訪問基類private的追答:
呵呵,我說的是 “外界無法直接訪問private和protected成員” 啊,再把上面的看看吧,這理解起來確實有些困難,可能第一段有誤解吧,我只是調侃的說法,意思是你說法中的”呼叫“和“public呼叫”是完全不一樣的概念,public呼叫是介面呼叫,而正常呼叫是直接呼叫資料成員。