#include<iostream>
class A {
public:
int a;
protected:
void func() {
std::cout<<"protected member"<<endl;
}
};
class B:public A
{
public:
using A::func; //Isn't this violation of encapsulation?
};
int main(){
B b;
b.func();
return 0;
}
为什么上面的代码成功运行?
它是否违反了封装的概念?
如果我错了,请纠正我。
答案 0 :(得分:3)
这是一个有趣的问题,我认为它强调了c ++中封装的一个重要且经常被忽视的方面。
我的回答是“是的,封装已被违反,但不是你认为的地方”。实际的违规行为是首先将方法声明为protected
。
您的代码很好地证明了与子类的受保护关系的问题......它们可以轻松地对您进行保护。另一种说法是,如果你要成为会员protected
,你也可以public
,因为实际上protected
是public
如果您的子类希望它成为。
这在实践中意味着什么?
这意味着如果你创建一个成员函数protected
,它永远是你类的接口的一部分。因此,您必须像对待任何其他公共成员函数一样认真对待,并且确实就好像它是公共成员函数一样。
也就是说它应尽可能无状态,尽可能少的前置条件,如果你改变实现,整个对象的逻辑效果必须保持不变。 / p>
答案 1 :(得分:2)
您所显示的示例不违反了封装,因为允许子类在其继承的内容之外添加公共成员,并且还允许他们访问他们继承的受保护成员
在您的情况下,B
的子类A
决定添加一个名为func
的新成员函数,其实现恰好包含{{1}的单个调用}。
通常,A::func
成员应被视为您班级 interface 的一部分,以及其protected
成员。尽管它们的可见性仅限于子类,但受保护的成员不属于类实现的一部分,因为对受保护成员命名或语义的任何更改都需要与对类的所有子类的更改进行协调。