首页 > 解决方案 > 如何防止基类的受保护成员仍然在子类的第二级被访问?

问题描述

一个例子来说明我的问题:

class Base
{
protected:
    int x{ 0 };
};

class DerivedClass1 : public Base
{
};

class DerivedClass2 : public DerivedClass1
{
public:
    int getX() const
    {
        return x;
    }
};

int main()
{
    DerivedClass2 d2{};
    int x{ d2.getX() };
    return 0;
}

我可以访问类BaseDerivedClass2受保护的成员,尽管受保护的成员Base应该只在DerivedClass1. 通过将变量继承BaseDerivedClass1一个类中,将形成一个DerivedClass2不得操纵的类。在 C# 中,这可以通过private protected关键字来实现,但是如何在 C++ 中处理它呢?

标签: c++classoopinheritanceprotected

解决方案


受保护的后果是什么?

protected允许所有派生类访问此类成员 正是这个想法。

虽然这是一个非常灵活的语言特性,但它在封装中造成了严重的弱点,它鼓励打破Liskov 替换原则(更准确地说是历史约束,因为派生类可以在不经过基类的情况下改变基对象的状态原始)。

如何避免它的弊端?

如果您想要更强大的封装和限制性访问,您需要转到private. 这确保了只能使用公共接口访问基类的内部状态。(请注意,虽然它确保了历史约束,但它本身并不能保证 LSP)。结果是没有派生类可以访问。不是第一次推导,也不是后来。

你需要私人保护吗?

你想要的是一种介于两者之间的:弱封装,但又不是太弱。这在 C++ 中不存在。而且我不确定它会加强你的设计。

但是,如果您在特殊情况下需要此限制,则可能有一种解决方法,使用名称查找:

class DerivedClass1 : public Base
{
private:
    using Base::x; 
// In DerivedClass1 you can still use x.
};

// But it will fail to compile in Derived2

在线演示

但我个人不建议这样做。它很容易出错(您可能会忘记using在一个兄弟中派生的)。编译器错误消息可能具有误导性。无论如何,私人会产生更强大的设计。


推荐阅读