[英]Do these two classes violate encapsulation?
class X
{
protected:
void protectedFunction() { cout << "I am protected" ; }
};
class Y : public X
{
public:
using X::protectedFunction;
};
int main()
{
Y y1;
y1.protectedFunction();
}
这样我就可以公开基类的一个功能。
你是自己做的。
你可以写
class Y : public X
{
public:
void doA()
{
protectedFunction();
}
};
int main()
{
Y y1;
y1.doA();
}
我认为没有理由担心它。
受保护的函数是继承树中可重用逻辑的一部分。 你可以隐藏它们,如果有一些内部逻辑或限制,或者像你的情况那样你可以暴露它,如果你确定这不会伤害任何人。
是的,这就是为什么受保护已经受到了公平的批评。
C ++的创建者Bjarne Stroustrup在他的优秀着作“C ++的设计和演变”中对此感到遗憾:
我对受保护的一个担忧正是因为它太容易使用一个共同的基础,就像人们可能已经习惯使用全局数据一样....回想起来,我认为受保护是一个“好的论据”和时尚克服的情况我更好的判断力和接受新功能的经验法则。
我认为正是Stroustrup本人说C ++中内置的封装和数据完整性功能旨在让诚实的人保持诚实,而不是阻止犯罪分子。
编号protectedFunction()受保护。 您可以从派生类中自由调用它,因此您可以直接从Y的公共成员调用它,并从main()调用此公共成员。
如果您可以使用私有方法完成此操作,则会出现问题...(编辑更清楚一点)。
从语言的角度来看,与在派生对象中创建委托方法相比,这不仅仅是对封装的违反:
class Y : public X
{
public:
void protectedFunction() {
X::protectedFunction();
}
};
一旦方法受到保护,它就会被提供给派生类,以便按照自己的意愿去做。 using
声明的意图不是更改继承的方法访问,而是避免方法隐藏的问题(如果定义了不同的重载,则X
中的公共方法将隐藏在类型Y
)。
现在,事实是,由于语言规则,它可以用于更改“已使用”方法的访问级别,如您的示例所示,但这并没有真正打开系统中的任何漏洞。 最后,派生类不能做任何比以前更多的事情。
如果实际问题是从设计的角度来看特定用法是否违反封装(这里的设计是应用程序设计,而不是语言设计),那么很可能是肯定的。 与公开内部数据或方法的方式完全相同。 如果它被设计为受X
的初始设计者保护,那么很可能Y
实现者不希望它被公开......(或者为同一目的提供委托方法)
没有。
要使用公共方法,您应该有一个Y
的实例,这将不起作用:
int main()
{
X y1;
y1.protectedFunction();
}
如果新定义中的Y暴露了一个新接口,那么Y.X仍然受到保护。
类设计者应该知道声明一个成员函数或变量(虽然所有变量应该是私有的,真的)作为受保护的大多数与声明它是公开的(因为你展示它很容易访问受保护的东西)。 考虑到这一点,在基类中实现这些功能时应注意考虑“意外”使用。 这不是对封装的违反,因为您可以访问它并公开它。
受保护只是一种宣传公开的更复杂的方式!
不,我真的没有看到问题。
而不是using
,你可以做到这一点:
class X
{
protected:
void protectedFunction() { cout << "i am protected" ; }
};
class Y : public X
{
public:
void protectedFunction() { X::protectedFunction(); }
};
任何类都可以接受任何可见的成员,并决定公开公开它。 这样做可能是糟糕的课堂设计,但它肯定不是语言中的缺陷。 私有或受保护成员的整个要点是,类本身必须决定谁应该访问该成员。 如果班级决定“我将给全世界访问”,那么这就是班级的设计方式。
如果我们遵循您的逻辑,那么getter和setter也会违反封装。 有时它们会这样做。 但不是因为语言被打破了。 仅仅因为你选择设计破碎的课程。
通过使成员受到保护,您可以为派生类提供对成员执行任何操作的自由。 他们可以看到它,因此他们可以修改它,或公开公开它。 当您保护成员时,您选择使这成为可能。 如果你不想那样,你应该把它变成私人的。
就个人而言,我认为这个问题应该更多地回答为设计问题而不是技术问题。
我会问,“首先,受保护的方法有什么意义?” 它是一个只有子类应该调用的方法,还是一个子类应该覆盖的方法? 但是,它可能是一种在通用基类中不期望的方法,但可能在子类中预期。 对于基类的客户端,他们从未知道该受保护的方法。 子类的创建者选择扩展合同,现在受保护的方法是公开的。 问题确实不应该是C ++允许的,但它适合你的课程,合同和未来的维护者。 当然它可能是一种难闻的气味,但实际上你需要使其适用于所涉及的用例。
如果确实将受保护的方法设为公开,请确保为维护者正确提供内部文档,说明为何做出此特定决策的理由。
一般来说,为了安全起见,作为前面提到的贡献者,您可能希望在子类中使用委托函数(具有不同的名称)。 因此,不是“get(int)”而是“getAtIndex(int)”或其他东西。 这使您可以更轻松地重构/保护/抽象/记录将来的文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.