很长一段时间以前,我正在查看由一位(现已离职的)同事编写的一些C ++代码,并发现了一个奇怪的类定义,我正试图破译。
class BaseClass
{
friend SubClass1;
friend SubClass2;
}
class SubClass1 : public BaseClass
{
...
}
class SubClass2 : public BaseClass
{
...
}
以这种方式设计类层次结构是否有好处?如果你想从子类访问BaseClass的私有方法,你不会只是将它们移动到protected而不是private吗?我觉得这里有一个成语我不知道。
答案 0 :(得分:7)
我不知道涉及到它的任何特定习语,但一个简单的答案可能是他们希望将私人成员仅暴露给许多子类中的几个子类。或者,他们可能很难理解受保护成员的概念。
答案 1 :(得分:6)
如果不看图书馆的真实设计,很难说,但这两种方法并不相同。以这种方式使用friend
可以通过声明所有成员protected
来提供对较少类型的访问权限。
更多访问权限
protected
的含义并非完全授予对派生类型所有基本成员的访问权限,而是授予对基本子对象内受保护成员的访问权限。派生类型。不同之处在于派生类型无法访问受保护的成员或不属于其自身类型或派生类型的类型。
考虑一个类的两个版本,其中一个类的所有成员都受到保护而没有友元声明,另一个版本的所有成员都是私有的,并将子类声明为朋友。现在考虑派生类型有一个函数:
struct derived : base {
void f( base& b ) {
//std::cout << b.protected_method() << std::endl; // Error
std::cout << protected_method() << std::endl; // Ok, accessing your own base
}
};
在使用protected
的情况下,问题是protected
不允许您调整除derived
以外的任何对象的内容或从derived
派生的类型,但参数可以是base
或任何其他类型base
,但与derived
无关。
在其他一些使用案例中,这个限制不太清楚,您可能能够获得对您自己的层次结构之外的 protected 成员的访问权限,而不是以一种简单的方式(I考虑语言的访问说明符规范中的错误)。
另一方面,如果derived
是base
的朋友,则上述代码将编译,因为derived
被授予访问任何地方的每个base
实例的权限,它是derived
的一个子对象。
更少类型
protected
访问说明符是转换的,一旦您通过protected
授予对派生类型的访问权限,您就会将其授予从中派生的所有类型,并且还授予可能继承的任何其他类型直接来自你。无法控制哪些类型被授予访问权限,哪些类型不被授予访问权限。另一方面,友谊是准确的,只有声明为朋友的类型的成员才能访问。友谊不是传递性的,因此您声明的朋友以外的其他类型将有权访问。
答案 2 :(得分:4)
不确定一个成语,但有一种可能性是你有其他子类。通过这种方式,朋友可以访问,但不能访问其他子类。
答案 3 :(得分:1)
在示例代码中,没有使用子类friend
。正如您所提到的,最好使成员protected
需要被其子类访问。否则它是代码气味。
但是,有一个一个真正的案例,其中一个必须将子类作为其基类的friend
。当你想要创建一个final class
时(就像在Java中一样)。以下是解释该案例的example code。
答案 4 :(得分:0)
我认为这只是一个糟糕的节目。无法想到任何可以从这种定义中获益的案例。