我看过一些抽象类的例子,其中有一个朋友operator<<
和一个虚拟的“print
”成员函数,其中两个声明都在protected
部分。例如:
class Function{
public:
virtual ~Function() {}
virtual double value(const double x) const = 0;
virtual Function* clone() const = 0;
protected:
friend ostream& operator<<(ostream& os, Function& f);
virtual void print(ostream& os) const = 0;
};
ostream& operator<<(ostream& os, Function& f){
f.print(os);
return os;
}
我不明白为什么这是强制性的。谁能解释一下?
谢谢!
答案 0 :(得分:1)
首先,声明friend
函数/运算符的位置并不重要。它不是public
,protected
或private
。它只是一个friend
函数/运算符,因此它可以访问类&#39;成员,无论他们的访问限制。因此,流运营商不受保护。它是friend
,这允许它访问print()
方法。
其次,print
方法应该是private
。如果你想从一个更加派生的类中调用基类的protected
方法,它只有print
才有意义。但是设计表明它是一个实现细节,以便实现ostream& operator<<
。
另一方面,如果您设计的课程使print
方法公开有意义,那么ostream& operator<<
就不需要friend
}。
答案 1 :(得分:0)
这当然不是强制性的。事实上,我认为它是 糟糕的设计。
你把朋友声明放在哪里并不重要;访问
加速器不适用于它。由于operator<<
是部分
公共接口,无论你在哪里声明它,它
在课堂的公共区域宣布它更有意义,
因为那是那些不是从类中派生的用户
寻找它。
关于print
功能,我也不是真的
除了公开之外宣布它的原因。鉴于最多,
如果不是所有访问都将通过朋友operator<<
,
它可能没关系,但我看不出有什么收获
声明它private
。作为一般规则,没有是
通过声明任何内容获得protected
;这是非常罕见的使用
protected
。在20世纪90年代中期,有人认为你应该这样做
声明virtaul函数protected
,而不是public
,和
标准库的一部分仍然反映了这个惯例。
但我认为今天的共识是1)如果这个规则
适用,虚函数应为private
,而不是
protected
,2)此规则并不总是适用于
const函数的情况,如print
,它实际上从来没有
适用。