为什么要将子类定义为其自己的父类的好友
Why define a subclass as a friend of its own parent class?
很久以前,我正在查看一位(现已离开的)同事编写的一些C++代码,并发现了一个我试图破译的奇怪类定义。
class BaseClass
{
friend SubClass1;
friend SubClass2;
}
class SubClass1 : public BaseClass
{
...
}
class SubClass2 : public BaseClass
{
...
}
以这种方式设计类层次结构有什么好处吗?如果你想从子类访问 BaseClass 的私有方法,你会不会将它们移动到受保护而不是私有?我觉得这里有一个成语我错过了。
如果不看库的真实设计,很难说,但这两种方法并不等同。以这种方式使用 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
无关。
在其他一些用例中,此限制不太清楚,您可能能够访问您自己的层次结构之外的那些受保护成员,只是不是以直接简单的方式(我认为这是语言的访问说明符规范中的错误)。
另一方面,如果derived
是base
的朋友,则上面的代码将编译,因为derived
被授予对任何地方的每个base
实例的访问权限,无论它是否是derived
的子对象。
到较小的类型
protected
访问说明符是可传递的,一旦通过protected
授予对派生类型的访问权限,就会将其授予派生自该类型的所有类型的,以及可能直接从您继承的任何其他类型。无法控制哪些类型被授予访问权限,哪些类型不被授予访问权限。另一方面,友谊是精确的,只有声明为朋友类型的成员才能访问。友谊不是可传递的,因此除了您声明的好友之外,还可以访问其他类型。
我不知道有任何特定的习语涉及这一点,但一个简单的答案可能是他们希望只向许多子类中的几个子类公开私有成员。或者,他们可能根本不了解受保护成员的概念。
不确定成语,但一种可能性是你还有其他子类。 这样,朋友就可以访问,但不能访问其他子类。
在示例代码中,没有用friend
的子类。正如你提到的,最好让成员protected
其子类需要访问的内容。否则就是代码异味。
但是,有一种真实的情况是,必须将子类作为其基类的friend
。这是你想要创建一个final class
的时候(就像在Java中一样)。下面是解释该极端情况的示例代码。
我认为这只是一个糟糕的编程。真的想不出任何你可以从这样的定义中受益的情况。
- C++调用使用重写函数的父类函数
- 具有纯虚函数和指针数组对象类型的父类的指针数组
- 创建自己的owner_ptr类;在传递堆栈或静态分配的地址时如何避免UB?
- 从多重继承中的派生类函数调用适当的父类函数
- 如何从继承的父类创建unique_ptr
- 尝试编写我自己的字符串类在 gcc 中出现异常
- 重写子类构造函数中的父类变量
- 自己的C++列表类实现(插入函数)出现问题
- 从C++中的父类实例访问子类方法
- 如何在 getter 的父类中初始化变量的情况下访问子类中的变量
- 内存覆盖在我自己的 Vector 类中
- 谁能帮我做我自己的矢量类
- C 如何制作从子类组件继承的父类
- 我必须声明自己的 wxFrame 类吗?
- 使用默认构造函数的父类;子类的析构函数意外调用
- 在声明纯虚函数的父类的实例上调用纯虚函数时会发生什么情况
- 在构造函数(C )中填写我自己的向量类
- 在 C++ 中实现自己的字符串类
- 为什么父类的父类方法在没有显式范围解析的情况下无法访问?
- 为什么要将子类定义为其自己的父类的好友