9.5 友元类成员
我们在第7章学过将函数声明为类友元的方法,友元函数有权自由访问任何类成员。当然,我们没有理由说友元函数不能是另一个类的成员。
假设我们定义了一个表示瓶子的CBottle类:
- class CBottle
- {
- public:
- CBottle(double height, double diameter)
- {
- m_Height = height;
- m_Diameter = diameter;
- }
-
- private:
- double m_Height; // Bottle height
- double m_Diameter; // Bottle diameter
- };
现在,我们需要有一个类来表示一打瓶子的包装箱,该类应该自动具有可容纳特定种类瓶子的定制尺寸。我们可能像下面这样进行定义:
- class CCarton
- {
- public:
- CCarton(const CBottle& aBottle)
- {
- m_Height = aBottle.m_Height; // Bottle height
- m_Length = 4.0*aBottle.m_Diameter; // Four rows of ...
- m_Width = 3.0*aBottle.m_Diameter; // ...three bottles
- }
-
- private:
- double m_Length; // Carton length
- double m_Width; // Carton width
- double m_Height; // Carton height
- };
这里的构造函数将包装箱的高度设定为与瓶子相同的高度,基于瓶子的直径将长度和宽度设定为刚好可以容纳12个瓶子。
我们现在知道,这样的定义不能工作。CBottle类的数据成员是private,因此CCarton类的构造函数不能访问它们。我们还知道,在CBottle类中使用friend声明可以修正该问题:
- class CBottle
- {
- public:
- CBottle(double height, double diameter)
- {
- m_Height = height;
- m_Diameter = diameter;
- }
-
- private:
- double m_Height; // Bottle height
- double m_Diameter; // Bottle diameter
- // Let the carton constructor in
- friend CCarton::CCarton(const CBottle& aBottle);
- };
这里的friend声明与第7章所介绍的friend声明之间的唯一区别是,我们为了识别友元函数而必须在其名称前面添加类名和作用域解析运算符。为了正确编译这条语句,编译器需要获得有关CCarton类构造函数的信息,因此我们需要在CBottle类的定义之前,添加一条#include语句以嵌入包含CCarton类定义的头文件。