如何防止基类的受保护成员仍然在子类的第二级被访问?
Posted
技术标签:
【中文标题】如何防止基类的受保护成员仍然在子类的第二级被访问?【英文标题】:How do you prevent protected members of the base class from still being accessed in the second level of the subclass? 【发布时间】:2019-07-19 09:54:25 【问题描述】:一个例子来说明我的问题:
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;
我可以在DerivedClass2
类中访问Base
的受保护成员,尽管Base
的受保护成员只能在DerivedClass1
中更改。通过将Base
中的变量继承到DerivedClass1
,应形成一个类,DerivedClass2
不得对其进行操作。在 C# 中,这可以通过 private protected
关键字来实现,但是在 C++ 中如何处理呢?
【问题讨论】:
受保护的数据几乎总是一个坏主意。简单地说,不要使用它。 感谢您的快速回复 - 嗯好的。 FWIW,C#private protected
访问级别也不是你想要的。
【参考方案1】:
受保护的后果是什么?
protected
的理念就是允许所有派生类访问这些成员。
虽然这是一个非常灵活的语言功能,但它在封装中造成了严重的弱点,这鼓励打破Liskov Substitution Principle(更准确地说是历史约束,因为派生类可以更改基础对象的状态而无需经过基类原语)。
如何避免它的弊端?
如果您想要更强大的封装和限制访问,您需要转到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
Online demo
但我个人不建议这样做。这很容易出错(您可能会忘记在一个同级派生中的using
)。编译器错误消息可能具有误导性。无论如何,私人会产生更强大的设计。
【讨论】:
【参考方案2】:您可以将数据成员声明为 private
并使用 friend
-declarations 明确指定哪些类可以访问它:
class Base
friend class DerivedClass1;
private:
int x = 0;
;
class DerivedClass1 : public Base
void test()
cout << x; // OK: DerivedClass1 is a friend of Base
;
class DerivedClass2 : public DerivedClass1
public:
int getX() const
return x; // ERROR: x is a private member
;
【讨论】:
是的,谢谢。当然,这将是一个折中的解决方案。 确实,这也是一种可能的解决方法。它的主要缺点是它强制Base
和Derived
之间存在强耦合,特别是Base
需要了解其所有潜在的一阶导数。不是真的OCP-friendly ;-)【参考方案3】:
继承一个“私有”基础:
class DerivedClass1 : private Base
;
编辑:通过 DerivedClass1 中的公共或受保护成员公开 Base 中的公共或受保护成员。然后,DerivedClass1 可以完全控制继承自 DerivedClass1 的类可以访问和不可以访问的 Base 成员。
这是否是一个好的解决方案取决于 Base 的复杂性。
【讨论】:
这当然是一个解决方案,但这仅在base
类没有公共成员时才有效。谢谢:)
真;这些成员需要通过 DerivedClass1 中的公共或受保护方法公开。以上是关于如何防止基类的受保护成员仍然在子类的第二级被访问?的主要内容,如果未能解决你的问题,请参考以下文章