2014-09-04 70 views
1

的對象訪問基類的受保護成員函數我們有兩個類:Base和Derived。在名爲PrintValue()的基類中有一個函數,它已被定義爲受保護的。派生類從Base類繼承此函數,但它可以通過在公開部分中聲明它來將其訪問說明符更改爲public。我的問題是:這是一個很好的軟件工程實踐嗎?爲什麼Derived類繼承了Base類的一個函數,能夠將該函數的訪問級別更改爲public,該類已經被Base類聲明爲protected。這樣,在主函數中,可以聲明Derived類的對象並訪問Base類的受保護函數,這違背了Base類的期望。C++使用派生類

class Base 
{ 
private: 
    int m_nValue; 

public: 
    Base(int nValue) 
     : m_nValue(nValue) 
    { 
    } 

protected: 
    void PrintValue() { cout << m_nValue; } 
}; 

class Derived: public Base 
{ 
public: 
    Derived(int nValue) 
     : Base(nValue) 
    { 
    } 

    // Base::PrintValue was inherited as protected, so the public has no access 
    // But we're changing it to public by declaring it in the public section 
    Base::PrintValue; 
}; 

int main() 
{ 
    Derived cDerived(7); 

    // PrintValue is public in Derived, so this is okay 
    cDerived.PrintValue(); // prints 7 
    return 0; 
} 

回答

3

你可以爭辯說Base聲明PrintValueprotected就像是說:「我相信派生類正確使用此成員」。因此,如果Derived決定公開曝光,則可以保留PrintValue的所有合同保證。

就良好做法而言,我強烈建議增加一個公共成員Derived,它在內部調用受保護的基本方法。

2

如果您的功能不應該被外界使用,使它私人。這是特別推薦的,如果它屬於你的基類的內部,並且你想保持自由來改變實現細節,或者外部世界的調用可以使你的對象處於不穩定狀態。

class Base { 
... 
private: // <==== HIDE DETAILS YOU DO NOT WANT TO EXPOSE 
    void PrintValue() { std::cout << m_nValue; } 
}; 
class Derived : public Base { 
... 
    Base::PrintValue; // <===NOW IT CAN'T COMPILE BECAUSE ACCESS IS PRIVATE ! 
}; 

如果您選擇,讓您的功能保護,那是因爲要放棄使用它來它的派生類的自由。但是你必須接受遊戲的規則:有了這種自由,你也可以放棄暴露自由的自由,或者直接(如你所示)或者通過一個調用受保護函數的自己函數來間接暴露它。這兩種情況並沒有如此不同:最終你的基本功能可以由外部人觸發到基類中!從軟件工程的角度來看,只要你對功能進行保護,你就會將它暴露給其他用戶(當然,這種用戶比公開曝光更受限制,但仍比私人曝光更多),並且你創造了期望值關於API的一些穩定性。所以引用斯科特邁耶斯:「保護沒有比公衆更封裝」。

+1

謝謝你的回答。所以我得到的是Base類不能盲目地信任Derived類,並假設任何東西都將它作爲受保護留在它們之間。實際上我並沒有期望派生類具備這種能力,特別是基於我以前的公有繼承經驗,即所有成員保持其原始訪問規範。私人會員保持私密,受保護的會員保持受保護,公共會員保持公開。 – 2014-09-04 19:18:29