2014-09-04 78 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