不看库的真实设计很难说,但这两种方法并不等价。与声明所有成员相比,以这种方式使用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
}
};
在 using 的情况下protected
,存在的问题是protected
不允许您调整除derived
或派生自的类型以外的任何对象的内容derived
,但参数可以是 abase
或任何其他扩展的类型,base
并且与derived
.
在其他一些用例中,此限制不太清楚,您可能能够访问您自己的层次结构之外的那些受保护成员,只是不是以直接简单的方式(我认为访问说明符规范中的一个错误)语言)。
另一方面,如果derived
是base
上面代码的朋友,则将编译,因为derived
被授予对base
任何地方的每个实例的访问权限,无论它是否是子对象derived
。
对于较小的类型
protected
访问说明符是可传递的,一旦您授予对派生类型的访问权限protected
,您就将其授予从它派生的所有类型,以及可能直接从您继承的任何其他类型。无法控制哪些类型被授予访问权限,哪些类型不被授予访问权限。另一方面,友谊是精确的,只有声明为朋友的类型的成员才能访问。友谊是不可传递的,因此您声明的朋友以外的类型将可以访问。