class X
{
protected:
void protectedFunction() { cout << "I am protected" ; }
};
class Y : public X
{
public:
using X::protectedFunction;
};
int main()
{
Y y1;
y1.protectedFunction();
}
这样我就可以公开基类的一个函数。
答案 0 :(得分:18)
你自己做了。
你可以写
class Y : public X
{
public:
void doA()
{
protectedFunction();
}
};
int main()
{
Y y1;
y1.doA();
}
我认为没有理由担心它 受保护的函数是继承树中可重用逻辑的一部分。你可以隐藏它们,如果有一些内部逻辑或限制,或者像你的情况那样可以暴露它,如果你确定这不会伤害任何人。
答案 1 :(得分:12)
是的,这就是为什么受保护已经受到了公平的批评。
C ++的创建者Bjarne Stroustrup在他出色的着作“C ++的设计与演变”中对此表示遗憾:
我对受保护的担忧之一是 确切地说它太容易了 以一种可能的方式使用共同的基础 懒散地使用了全球数据.... 回想起来,我认为受保护的是 一个“好的论据”和 时尚克服了我更好的判断力 和我接受的经验法则 新功能。
答案 2 :(得分:11)
我认为正是Stroustrup本人说C ++中内置的封装和数据完整性功能旨在让诚实的人保持诚实,而不是阻止犯罪分子。
答案 3 :(得分:3)
没有。 protectedFunction()受保护。您可以从派生类中自由调用它,因此您可以直接从Y的公共成员调用它,并从main()调用此公共成员。
如果您可以使用私有方法完成此操作,则会出现问题... (编辑有点清楚)。
答案 4 :(得分:2)
从语言的角度来看,这并不比在派生对象中创建委托方法更违反封装:
class Y : public X
{
public:
void protectedFunction() {
X::protectedFunction();
}
};
一旦方法受到保护,就会根据需要将它提供给派生类。 using
声明的意图不是改变继承的方法访问,而是避免方法隐藏的问题(如果不同的重载是X
中的公共方法隐藏在类型Y
中定义)。
现在,由于语言规则,它可用于更改“已使用”方法的访问级别,如您的示例所示,但这并未真正打开系统中的任何漏洞。最后,派生类不能做任何比以前更多的事情。
如果实际问题是从设计的角度来看特定用法是否违反了封装(这里的设计是应用程序设计,而不是语言设计),那么很可能是肯定的。与公开内部数据或方法的方式完全相同。如果它被设计为受X
的初始设计者保护,那么Y
实现者可能不希望它被公开......(或为同一目的提供委托方法)< / p>
答案 5 :(得分:2)
没有。
要使用公共方法,您应该拥有Y
的实例,这将不起作用:
int main()
{
X y1;
y1.protectedFunction();
}
如果新定义中的Y暴露了一个新接口,它就是Y.X仍然受到保护。
答案 6 :(得分:2)
在C ++中,即使是私有修饰符也不能保证封装。没有人可以阻止你在脚下射击自己。
Herb Sutter在他的文章“Uses and Abuses of Access Rights”中阐述了如何“打破封装”的不同方式。
这是赫伯文章中的有趣例子。
邪恶的宏魔法
#define protected public // illegal
#include "X.h"
//...
X y1;
y1.protectedFunction();
答案 7 :(得分:1)
类设计者应该知道声明一个成员函数或变量(尽管所有变量应该是私有的,真的)作为受保护的大多数与声明它是公开的(因为你展示它很容易获得受保护的东西)。 考虑到这一点,在基类中实现这些功能时应注意考虑“意外”使用。这不是对封装的违反,因为您可以访问它并公开它。
受保护只是宣传公开事物的一种更复杂的方式!
答案 8 :(得分:1)
不,我真的没有看到问题。
而不是using
,你可以这样做:
class X
{
protected:
void protectedFunction() { cout << "i am protected" ; }
};
class Y : public X
{
public:
void protectedFunction() { X::protectedFunction(); }
};
任何类都可以接受任何可见的成员,并决定公开公开它。这样做可能是糟糕的课堂设计,但它肯定不是语言中的缺陷。私有或受保护成员的整个要点是,类本身必须决定谁应该访问该成员。如果班级决定“我将给全世界访问”,那么这就是班级的设计方式。
如果我们遵循您的逻辑,那么getter和setter也会违反封装。有时它们会这样做。但不是因为语言被打破了。仅仅因为你选择设计破碎的课程。
通过使成员受到保护,您可以为派生类提供与成员一起任何他们喜欢的自由。他们可以看到它,因此他们可以修改它,或公开公开它。当您保护成员时,您选择使这成为可能。如果你不想那样,你应该把它变成私有的。
答案 9 :(得分:1)
我个人认为这个问题应该作为设计问题而不是技术问题来回答。
我会问,“首先,受保护的方法有什么意义?”它是一个只有子类应该调用的方法,还是一个子类应该覆盖的方法?但是,它可能是一种在通用基类中不期望的方法,但可能在子类中预期。对于基类的客户端,他们从未知道该受保护的方法。子类的创建者选择扩展合同,现在受保护的方法是公开的。问题确实不应该是C ++允许的,但它适合你的课程,合同和未来的维护者。当然它可能是一种难闻的气味,但实际上你需要使它适用于所涉及的用例。
如果您确实将受保护的方法设为公开,请确保为维护人员正确提供内部文档,说明为何做出此特定决策的理由。
一般来说,为了安全起见,作为前面提到的贡献者,您可能希望在子类中使用委托函数(具有不同的名称)。因此,不是“get(int)”而是“getAtIndex(int)”或其他东西。这使您可以更轻松地重构/保护/抽象/记录该文件。