c++ - 如何防止基类的受保护成员仍然在子类的第二级被访问?
问题描述
一个例子来说明我的问题:
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;
}
我可以访问类Base
中DerivedClass2
受保护的成员,尽管受保护的成员Base
应该只在DerivedClass1
. 通过将变量继承Base
到DerivedClass1
一个类中,将形成一个DerivedClass2
不得操纵的类。在 C# 中,这可以通过private protected
关键字来实现,但是如何在 C++ 中处理它呢?
解决方案
受保护的后果是什么?
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
在一个兄弟中派生的)。编译器错误消息可能具有误导性。无论如何,私人会产生更强大的设计。
推荐阅读
- performance - Chrome + 开发工具性能不佳
- google-workspace - 无法从谷歌工作区市场找到 Colaboratory
- python - python、bs4、.csv——为什么我的函数不能正确重复?
- react-native - React native android scrollview - 未应用内容插入/内容偏移
- typescript - cy.intercept() 不在赛普拉斯中存根 API
- r - lm_model 添加的意外符号错误
- powershell - 将 PowerShell cmdlet 的错误级别传递给批处理文件
- javascript - 似乎无法在 three.js 中向场景添加文本
- python - 来自数据框的 Python networkx 绘图,线宽取决于列值
- stackexchange.redis - 无法使用 SSL 连接到 Azure Cache for Redis