一前言
看c++ primer有一個地方看的云里霧里的,這么一段話
可以認為 protected 訪問標號是 private 和 public 的混合:
? 像 private 成員一樣,protected 成員不能被類的用戶訪問。
? 像 public 成員一樣,protected 成員可被該類的派生類訪問。
此外,protected 還有另一重要性質:
? 派生類只能通過派生類對象訪問其基類的 protected 成員,派生類對其基類類型對象的 protected 成員沒有特殊訪問權限
這里就完全看不明白了,freeeim可能是翻譯的問題導致的,老外寫的本來就有點繞,翻譯過來就更加繞,很難理解。
那么我們以下面的代碼為例子。大家先看看覺得那句話編譯會報錯。
我之前寫的代碼都是編譯錯了之后,自己再去修改,而沒有特別仔細的去思考到底為什么定義為pubulic ,protected和private,總是到這里弄不清楚,稀里糊涂就過去了,為了弄清楚,敲了下面的代碼,編譯之后便一目了然了。
二分析代碼
先自己分析一下,然后后面在公布答案。
[cpp] view plaincopyprint?
class A?? {? public:? ??????? int set(A& a);? ??????? int public_a_var;? protected:? ??????? int protected_a_var;? private:? ??????? int private_a_var;? };? ? ? int A::set(A &a)? {? ??????? protected_a_var = a.protected_a_var;? ??????? private_a_var = a.private_a_var;? ??????? public_a_var = a.public_a_var;? }? class B:A? {? ??????? public:? ??????????????? int anotherset(A& a, B& b);? ??????????????? int public_b_var;? ??????? protected:? ??????????????? int protected_b_var;? private:? ??????????????? int private_b_var;? };? ? ? int B::anotherset(A& a, B& b)? {? ??????? public_b_var = a.public_a_var ;? ??????? public_b_var = b.public_b_var;? ??????? protected_b_var = a.protected_a_var;? ??????? protected_b_var = b.protected_b_var;? ??????? private_b_var = a.private_a_var;? ??????? private_b_var = b.private_b_var;? ? ? ? ? ??????? public_a_var = a.public_a_var ;? ??????? public_a_var = b.public_b_var;? ??????? protected_a_var = a.protected_a_var;? ??????? protected_a_var = b.protected_b_var;? ??????? private_a_var = a.private_a_var;? ??????? private_a_var = b.private_b_var;? }? ? ? int main()? {? ??????? A main_a;? ??????? int a = main_a.private_a_var;? ??????? int b = main_a.protected_a_var;? ??????? int c = main_a.public_a_var;? }?
class A
{
public:int set(A& a);int public_a_var;
protected:int protected_a_var;
private:int private_a_var;
};int A::set(A &a)
{protected_a_var = a.protected_a_var;private_a_var = a.private_a_var;public_a_var = a.public_a_var;
}
class B:A
{public:int anotherset(A& a, B& b);int public_b_var;protected:int protected_b_var;
private:int private_b_var;
};int B::anotherset(A& a, B& b)
{public_b_var = a.public_a_var ;public_b_var = b.public_b_var;protected_b_var = a.protected_a_var;protected_b_var = b.protected_b_var;private_b_var = a.private_a_var;private_b_var = b.private_b_var;public_a_var = a.public_a_var ;public_a_var = b.public_b_var;protected_a_var = a.protected_a_var;protected_a_var = b.protected_b_var;private_a_var = a.private_a_var;private_a_var = b.private_b_var;
}int main()
{A main_a;int a = main_a.private_a_var;int b = main_a.protected_a_var;int c = main_a.public_a_var;
}
三含義介紹
1 類成員的含義
首先說一下概念,c++ primer里面類成員,類對象,類用戶,這些詞語在c++ primer里面用的亂七八糟的,讓人看著很費解,如果你本身又是學過別的c++的書籍,看到上面的一段話估計要崩潰的,講的是嘛啊?
2 類對象的含義
先解釋一下上面這句話:
這里類成員這個詞沒有任何歧義,就是指類里面的所有變量和函數。
類對象這個詞存在歧義,而且這本書里面前后都不一樣,要看語境了。
第一種是廣義的
比如上文中的,main函數里面的main_a ,set函數里面的a,anotherset函數里面的a, b 都是類對象,而且這本書里面的大部分地方類對象就是廣義的。
第二種是狹義的,專指類的成員函數里面的作為參數的類對象。
在某些語境里面,個人覺得一般是出現了類的用戶這個詞之后,類對象就變成狹義了。
上面那句話里面“派生類只能通過派生類對象訪問其基類的 protected 成員”,
其實這里可以這么理解吧,派生類的進行什么操作,描述的就是類的函數了,前面加入了條件限制了,那么這個類對象自然就也被限定了起來。
不過讀起來就很費勁了。
3 類的用戶
這個詞語在一般的c++書上貌似是看不到的,突然之間冒出來一個類的用戶,就突然感覺復雜了很多。
其實如果第一句話修改為:
像 private 成員一樣,protected 成員不能被類的對象訪問。
這個時候,你在看第三句話,就會有疑問,既然protect成員不能被類的對象訪問,那怎么又“派生類只能通過派生類對象訪問其基類的 protected 成員”,這不是前后矛盾么?
其實并不矛盾,作者也是怕用戶看到這里看糊涂了,就引入了類的用戶。
類的用戶,可以專門指外部函數里面的類的對象,例如main函數里面的main_a ,其他幾個就不是類的用戶了。
四進一步分析
我們分析一下上面的這一段話,其實有一個前提,沒說說明白。
因為作者認為大部分人都應該知道,所以就沒有說,也沒有強調,但是很多人都是半生不熟的c++然后來看這本書,知道它是經典,但是不知道它不是prime,至少你得寫了一年的c++代碼,至少你得吃過苦頭才能明白。
廢話不說了,前提是:
類的成員函數中的類對象,可以訪問自己的所有類型的成員。
換句話說,狹義的類對象,可以訪問自己的所有類型的成員。
類的成員函數中其實是個定語,雖然很長。
第三句話的前半段,“派生類只能通過派生類對象訪問其基類的 protected 成員”,因為派生類已經繼承了基類,所以protected也是它自己的成員,基于這個前提,它狹義的類對象,自然可以訪問自己的protected變量。
第三局話的后半段,當基類對象作為參數的時候,這句話更繞,我們用繼承類代替前面那句話的類,就是由于基類對象不屬于繼承類的成員函數的繼承類對象,所以它本質上不屬于這個繼承類的對象,所以它的權限就和類的用戶是一樣的。
五分析代碼
上面已經把人說暈了,我分析下代碼吧。
[cpp] view plaincopyprint?
int A::set(A &a)? {? ??????? protected_a_var = a.protected_a_var;? ??????? private_a_var = a.private_a_var;? ??????? public_a_var = a.public_a_var;? }?
int A::set(A &a)
{protected_a_var = a.protected_a_var;private_a_var = a.private_a_var;public_a_var = a.public_a_var;
}
這三句話都正確。
這里有兩個概念,protected_a_var ,private_a_var已經public_a_var實質是this.開頭的,指的是類的成員(其實也是類當前對象的成員),入參是類型A的對象a,由于類型一樣,所以可以操作a的任何變量。
這個原理我不知道,面向對象的思想吧,其實面向對象就是仿照人類社會。我們可以這么理解如果大家是一類,或者看成一家人,在構建這個家庭的時候,我們內部的各種東西都是共享的。
但是當我們出了這個家門,在外面的時候,只有我們家公共的信息可以告訴別人,但是私有的密碼,必然家里多少錢,銀行密碼之類的就不能說了。
[cpp] view plaincopyprint?
int B::anotherset(A& a, B& b)? {? ??????? public_b_var = a.public_a_var ;? ??????? public_b_var = b.public_b_var;? ??????? protected_b_var = a.protected_a_var;? ??????? protected_b_var = b.protected_b_var;? ??????? private_b_var = a.private_a_var;? ??????? private_b_var = b.private_b_var;? ? ? ? ? ??????? public_a_var = a.public_a_var ;? ??????? public_a_var = b.public_b_var;? ??????? protected_a_var = a.protected_a_var;? ??????? protected_a_var = b.protected_b_var;? ??????? private_a_var = a.private_a_var;? ??????? private_a_var = b.private_b_var;? }?
int B::anotherset(A& a, B& b)
{public_b_var = a.public_a_var ;public_b_var = b.public_b_var;protected_b_var = a.protected_a_var;protected_b_var = b.protected_b_var;private_b_var = a.private_a_var;private_b_var = b.private_b_var;public_a_var = a.public_a_var ;public_a_var = b.public_b_var;protected_a_var = a.protected_a_var;protected_a_var = b.protected_b_var;private_a_var = a.private_a_var;private_a_var = b.private_b_var;
}
看看這段代碼,繼承其實就像分家了,我們有一些共有的東西,也有一些私有的東西,但是也不是特別的貼切這個比喻。這樣吧,就像娶老婆了。老婆說,你的都是我的,我的還是我的。其實都不貼切,如果大家看過龍珠的話,可以這么認為,就像是那美克星人的生殖,兒子繼承類父親的所有能力,而且自己還會不斷進步。
廢話不說了,我們還是分析加上必要的記憶吧。
先看前六句:
我們根據上面的理解,賦值語句前面的變量,class B都可以訪問,后面的如果類型是class B的因為是一家人都可以訪問,a 的只能訪問public類型的,所以結果為
[cpp] view plaincopyprint?
????????????? public_b_var = a.public_a_var ;? public_b_var = b.public_b_var;? protected_b_var = a.protected_a_var;? protected_b_var = b.protected_b_var;? private_b_var = a.private_a_var;? private_b_var = b.private_b_var;?
public_b_var = a.public_a_var ;public_b_var = b.public_b_var;protected_b_var = a.protected_a_var;//錯誤,a.protected_a_var是保護的。protected_b_var = b.protected_b_var;private_b_var = a.private_a_var;//錯誤,a.private_a_var是私有的private_b_var = b.private_b_var;
下面六句話,繼承的時候,繼承類的成員只能訪問protect和pirvate所以結果如下
[cpp] view plaincopyprint?
????????????? public_a_var = a.public_a_var ;? public_a_var = b.public_b_var;? protected_a_var = a.protected_a_var;? protected_a_var = b.protected_b_var;? private_a_var = a.private_a_var;? private_a_var = b.private_b_var;?
public_a_var = a.public_a_var ;public_a_var = b.public_b_var;protected_a_var = a.protected_a_var;//錯誤,a.protected_a_var是保護的。protected_a_var = b.protected_b_var;private_a_var = a.private_a_var;// 兩個錯誤,private_a_var 和a.private_a_var都不能訪問,是私有的private_a_var = b.private_b_var;//private_a_var是私有的,賦值語句前面的那個
最后分析main函數里面的
[cpp] view plaincopyprint?
int a = main_a.private_a_var;? int b = main_a.protect_a_var;? int c = main_a.public_a_var;?
int a = main_a.private_a_var;//錯誤,a.private的私有int b = main_a.protect_a_var;//錯誤,a.protect是保護int c = main_a.public_a_var;
6 結果。
大家可以編譯測試一下:上面文章有原因,本來想標記為紅色,但是代碼類型的不會標記,如果有達人知道,希望在評論里面回復一下,便于大家查看代碼。
[cpp] view plaincopyprint?
<span style="font-size: 14px;">class A?? {? public:? ??????? int set(A& a);? ??????? int public_a_var;? protected:? ??????? int protected_a_var;? private:? ??????? int private_a_var;? };? ? ? int A::set(A &a)? {? ??????? protected_a_var = a.protected_a_var;? ??????? private_a_var = a.private_a_var;? ??????? public_a_var = a.public_a_var;? }? class B:A? {? ??????? public:? ??????????????? int anotherset(A& a, B& b);? ??????????????? int public_b_var;? ??????? protected:? ??????????????? int protected_b_var;? private:? ??????????????? int private_b_var;? };? ? ? int B::anotherset(A& a, B& b)? {? ??????? public_b_var = a.public_a_var ;? ??????? public_b_var = b.public_b_var;? ??????? protected_b_var = a.protected_a_var;? ??????? protected_b_var = b.protected_b_var;? ??????? private_b_var = a.private_a_var;? ??????? private_b_var = b.private_b_var;? ? ? ? ? ??????? public_a_var = a.public_a_var ;? ??????? public_a_var = b.public_b_var;? ??????? protected_a_var = a.protected_a_var;? ??????? protected_a_var = b.protected_b_var;? ??????? private_a_var = a.private_a_var;? ??????? private_a_var = b.private_b_var;? }? ? ? int main()? {? ??????? A main_a;? ??????????????? int a = main_a.private_a_var;? ??????? int b = main_a.protected_a_var;? ??????? int c = main_a.public_a_var;? }</span>?
class A
{
public:int set(A& a);int public_a_var;
protected:int protected_a_var;
private:int private_a_var;
};int A::set(A &a)
{protected_a_var = a.protected_a_var;private_a_var = a.private_a_var;public_a_var = a.public_a_var;
}
class B:A
{public:int anotherset(A& a, B& b);int public_b_var;protected:int protected_b_var;
private:int private_b_var;
};int B::anotherset(A& a, B& b)
{public_b_var = a.public_a_var ;public_b_var = b.public_b_var;protected_b_var = a.protected_a_var;//errorprotected_b_var = b.protected_b_var;private_b_var = a.private_a_var;//errorprivate_b_var = b.private_b_var;public_a_var = a.public_a_var ;public_a_var = b.public_b_var;protected_a_var = a.protected_a_var;//errorprotected_a_var = b.protected_b_var;private_a_var = a.private_a_var;//errorprivate_a_var = b.private_b_var;//error
}int main()
{A main_a;int a = main_a.private_a_var;//errorint b = main_a.protected_a_var;//errorint c = main_a.public_a_var;
}
總結
以上是生活随笔為你收集整理的【转载】c++之类的基本操作(c++ primer 的读书笔记 ,类对象, 类用户, 类成员的含义)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。