我们有两个类:Base和Derived。 Base类中有一个名为PrintValue()的函数,它已被定义为protected。派生类从Base类继承此函数,但它可以通过在公共部分中声明它来将其访问说明符更改为public。我的问题是:这是一个很好的软件工程实践吗?为什么Derived类从Base类继承了一个函数,能够将该函数的访问级别更改为public,该类已经被声明为Base类保护。这样,在main函数中,您可以声明Derived类的对象并访问Base类的受保护函数,这违背了Base类的期望。
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;
}
答案 0 :(得分:3)
您可以争辩Base
声明PrintValue
protected
就像在说:&#34;我相信派生类正确使用此成员&#34;。因此,如果Derived
决定公开公开,那么只要保留PrintValue
的所有合同保证,就可以了。
在良好实践方面,我强烈希望将公共成员添加到内部调用受保护的基本方法的Derived
。
答案 1 :(得分: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的一些稳定性。所以引用斯科特迈耶斯:&#34;受保护不再是公共封装。&#34;