2026/2/17 0:29:52
网站建设
项目流程
服装商店的网站建设要求,网站开发用什么系统,网站注册怎么做,深圳市平面设计协会《你真的了解C吗》No.027#xff1a;访问权限#xff1a;不仅仅是访问控制——受保护成员的语义陷阱
导言#xff1a;封装的灰色地带
在 C 中#xff0c;protected 的初衷是提供一种“温和的封装”#xff1a;它对外界保持封闭#xff0c;但对子类保持开放。这种设计初衷…《你真的了解C吗》No.027访问权限不仅仅是访问控制——受保护成员的语义陷阱导言封装的灰色地带在 C 中protected的初衷是提供一种“温和的封装”它对外界保持封闭但对子类保持开放。这种设计初衷是好的但在实际的物理规则下它引发了一个让无数初学者甚至老手都感到困惑的访问限制。一、 语义陷阱谁能访问谁的protected请看这个经典的案例它揭示了 C 权限控制中一个非常冷酷的逻辑classBase{protected:intvalue;};classDerived:publicBase{public:voidtest(Derivedd,Baseb){d.value10;// 成功通过派生类对象访问自己的成员b.value10;// 错误编译失败不能访问基类对象的受保护成员}};物理真相派生类只能访问**“属于自己那一部分”**的基类成员。编译器禁止你通过基类指针或对象去访问protected成员是为了防止以下情况如果你能通过Base b修改value那么我只需要写一个临时类class Hack : public Base就可以在Hack内部随意修改全世界任何一个Base对象甚至是Derived以外的其他子类对象的私有保护数据。这会导致封装性彻底崩溃。二、protected成员维护性的灾难在架构设计上protected成员其实是**“针对派生类的公有接口”**。承诺的枷锁一旦你把一个成员变量设为protected你就相当于向所有未来的子类承诺这个变量的名字、类型和含义将永远不变。重构困难如果你某天想把这个变量从int改成double或者想彻底删除它你会发现你需要翻遍整个工程修改所有继承自你的类。底层建议永远不要把数据成员设为protected。如果你想让子类访问请提供protected的Getter/Setter函数。这样当你改变内部实现时至少可以保持函数接口不变。三、 权限的“过滤器”效应我们在 No.023 聊过私有继承现在我们从物理布局的角度总结一下三种继承方式如何过滤基类成员的可见性基类成员类型public 继承后protected 继承后private 继承后publicpublicprotectedprivateprotectedprotectedprotectedprivateprivate不可见不可见不可见物理本质继承方式实际上是规定了基类成员在派生类中的上限可见度。public继承保持原样Is-a 关系。private继承将所有基类特征“漂白”为私有这通常意味着你终结了该类进一步被他人继承并利用基类功能的可能性。四、 现代 C 的观点在现代 C 的设计哲学中大家倾向于要么 public纯粹的接口。要么 private彻底的封装。尽量不用 protected因为它往往意味着设计上的模棱两可。总结防线的选择public展示给全世界看的“脸面”。protected只传给后代的“家传秘籍”但即便在家里你也不能去动长辈的东西。private只有自己知道的“心事”连后代都无法窥探。下一篇预告既然封装防线如此严密有没有一种“后门”可以让一个完全无关的类直接翻墙进入你的私有领地➡️《你真的了解C吗》No.028友元friend的必要性与边界——为什么它不是对封装的破坏