C ++使用Derived类的对象访问Base类的受保护成员函数

C++ accessing protected member function of Base class with an object of Derived class

我们有两个类:基类和派生类。基类中有一个名为printValue()的函数已定义为protected。派生类从基类继承此函数,但它可以通过在public节中声明来将其访问说明符更改为public。我的问题是:这是一个好的软件工程实践吗?为什么派生类(它从基类继承了一个函数)能够将该函数的访问级别更改为public,而public已经声明为受基类保护。这样,在主函数中,您可以声明派生类的对象并访问基类的保护函数,这与基类的期望相反。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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;
}


你可以说,Base声明PrintValueprotected就像是说:"我相信派生类可以正确地使用这个成员"。因此,如果Derived决定公开披露,只要保留PrintValue的所有合同担保,就可以了。

在良好的实践中,我强烈希望在内部调用受保护基方法的Derived中添加一个公共成员。


如果外部世界不应该使用您的功能,请将其设为私有。如果它属于您的基类的内部,并且您希望保持更改实现细节的自由,或者外部世界的调用可能会使您的对象处于不稳定状态,则特别建议这样做。

1
2
3
4
5
6
7
8
9
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稳定性的期望。所以引用斯科特·迈耶斯的话:"受保护的不比公共的更封闭。"