c 派生類向基類轉換的可訪問性

2022-05-08 21:48:07 字數 3279 閱讀 3697

1.成員函式和友元函式、友元類的許可權是一樣一樣一樣一樣的,是最高的許可權,private、protected、public成員都可以隨意訪問。

2.使用者**(類外呼叫的其他**)許可權是最低的,只有類的public成員才能訪問(不考慮靜態成員),protected、private都無法訪問。

3.繼承體系,如類b繼承於類a,只要有private(不管是a的private還是b的繼承方式)都會得到private;沒有private的,只要有protrected都會得到protected;其他的都是public。這樣實際的意義是:基類私有的變數,你不能通過繼承,還反而變成公有了,那豈不是型別不安全了?隨便繼承下就可以改動基類的資料了!另外:初學者都喜歡背繼承規則(我當時就是),不要死記那個繼承方式表,沒有用,要理解原因!

基於以上兩個前提,有以下性質:

**於:

,同時新增了自己的註解(加粗部分)

宣告:加粗的解釋是我個人的理解,不保證正確性!

1.如果派生類以public繼承基類,則是is a關係,用派生類可以完成基類的所有功能,所以可以在任意地方將派生類自動轉換成基類,注意,這裡都是指指標或引用,而不是物件。 比如:

class a{};

class b:public a{}

b b;

void function(const a &);

這時就可以使用function(b),會預設把b型別轉換成a型別。

解釋:動態多型的內容

2.假定d繼承b:

不論d以什麼方式繼承b,d的成員函式和友員函式都能使用派生類向基類的轉換;派生類向其直接基類的型別轉換對於派生類的成員函式和友員函式來說永遠是可訪問的。

例如:class b{}

class d:private b                //這裡以private或者protected或者public 都可以

void f()

b * base=new d;                      //編譯正確

解釋:前提說過:成員函式和友元函式的許可權是最高的,派生類-->基類,也並不會造成資料不安全,所以可以。

如果不是成員函式(即使用者**),例如:

class b{};

class d:private b                //如果這裡是public就可以,private或protected會錯

*/};

int main()

;解釋:如果b * b=new d;可以編譯成功,是想幹什麼?顯然是要多型,動態呼叫b類/d類的不同版本的函式。那麼我們假設b類的乙個public函式f,d類繼承該函式f,但注意是private/protected,所以d類的f函式也對應的為:private或者protected。那麼問題也就變成了另乙個問題:使用者**可以呼叫乙個類的private/protected成員函式嗎?不可以阿!所以b * b=new d;這樣寫的目的(多型)是無法達到的,那麼也就沒有存在的意義,所以c++語法規定這種呼叫不能通過編譯是合情合理的。

3.如果d繼承b的方式是public或者protected,則d的派生類的成員或者友員可以使用d向b的型別轉換;反之,如果d繼承b的方式是private,則不能使用。

class b{};

class d:public b{};//public或protected都可以

class e:private d或者protected d或者public d

void f()

b *b=new d;              //可以編譯通過

d *d=new e;            //可以編譯通過,這就是2介紹的情況。

解釋:

只說第一行:b* b=new d;為什麼能編譯通過。逆向思維,為什麼要這樣寫,這樣能通過編譯是為了做什麼?肯定是要動態呼叫b或d類的不同版本函式(多型),對吧?假設b的乙個public成員函式f,d類(public繼承b)裡是可以繼承該f函式的,所以e類(繼承於d,什麼方式無所謂)也繼承了d類的f函式,也就是說b類的f函式經過繼承體系,最終在e類裡可見,可以通過b類物件來呼叫這個f函式。所以b* b=new d;能編譯成功,必然有其意義在,有意義才有存在的理由,不然就沒有存在的價值。(有點哲學意味,但我認為這樣反推是有道理的。)

但是如果變成private繼承:

class b{};

class d:private b{};

class e:private d或者protected d或者public d

void f()

b *b=new d;              //錯,不可以編譯

d *d=new e;            //可以編譯,這就上2介紹的情況

解釋:

只說第一行:b* b=new d;為什麼無法通過編譯。還是和上面一樣的想法:b類有沒有成員可以被e類呼叫/使用的?如果有,那麼就應該可以編譯成功,但是實際編譯失敗,那麼我們來看看到底行不行:

假設b類的乙個public成員函式f,在d類(private繼承b)中,f函式可以繼承於b類的,但屬性變成了private。e類再繼承d類,e類肯定無法繼承d類的f函式了,對不對?(這時候就不要考慮b類了,這樣想:d類是基類,有乙個private成員函式f,e類繼承於d類,e類顯然繼承不了這個f函式)也就是說,經過我們分析,b類的public成員都無法在e類中被呼叫/使用,更不用說b類的protected/private成員了。結論:由於b類的任何成員都無法被e類繼承,那麼e類中就不應該允許b *b=new d; 這樣的呼叫存在,因為根本就沒有任何成員/函式給它進行多型!

繼承體系測試**:

#includeusing

namespace

std;

class

a{};

class b:public

a{};

class c:protected

a{};

class d:private

a{};

class e:public

b{};

class f:public

c{};

class g:public

d{};

intmain()

C 派生類向基類轉換的可訪問性

派生類向基類到轉換是否可訪問由使用該轉換到 決定,同時派生類到派生訪問說明符也會有影響。假定d繼承自b 上買的定義是摘自c primer 裡面的定義,聽起來是不是很繞口,所以下面就結合 通俗的解釋下 先看第一問吧,是什麼意思,定義三個類如下 include define cout str std c...

C 筆記 派生類到基類轉換到可訪問性

使用者 指的是除友元函式,成員函式之外的 後代類,不僅僅指第一級派生類,還包括間接派生自基類的後續的派生類。派生類,這裡專指 直接繼承類。include using namespace std class a class b public a class c protected a class d ...

C 筆記 派生類到基類轉換到可訪問性

c 筆記 派生類到基類轉換到可訪問性 要確定到基類的轉換是否可訪問,可以考慮基類的public成員是否可訪問,如果可以,轉換是可以訪問的,否則,轉換是不可訪問的。如果是public繼承,則使用者 和後代類都可以使用派生類到基類的轉換。如果類是使用private或protected繼承派生的,則使用者...