-1

我已经看到了一些带有朋友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;
}

我不明白为什么这是强制性的。有人可以解释吗?

谢谢!

4

2 回答 2

1

首先,在哪里声明friend函数/运算符并不重要。不是publicprotected或者private。它只是一个friend函数/运算符,因此它可以访问类的成员,而不管它们的访问限制。所以流操作符不受保护。它是一个friend, 这允许它访问该print()方法。

其次,print方法大概应该是privateprotected只有当您想print从更派生的方法调用基类的方法时,它才有意义。但设计表明它是一个实现细节以便实现ostream& operator<<

另一方面,如果你设计了你的类,使得方法公开是有意义的,那么就print不需要.ostream& operator<<friend

于 2013-07-28T14:25:22.513 回答
0

这当然不是强制性的。事实上,我认为这是糟糕的设计。

你把朋友声明放在哪里并不重要;访问修饰符不适用于它。由于它operator<< 公共接口的一部分,无论您在哪里声明它,在类的公共区域中声明它更有意义,因为不是从该类派生的用户会在那里寻找它。

关于print功能,我也没有真正的理由将其声明为公开。鉴于大多数(如果不是所有)对它的访问都将通过朋友进行operator<<,这可能并不重要,但我看不出通过声明它可以获得什么private。作为一般规则,声明任何东西都不会protected获​​得任何东西;这是非常罕见的使用 protected。在 1990 年代中期,有人认为应该声明 virtaul 函数protected,而不是public,并且标准库的部分内容仍然反映了这种约定。但我认为今天的共识是 1)如果这个规则适用,虚函数应该是private,不是 protected,并且 2)这个规则并不总是适用——在 const 函数的情况下,比如print,它实际上从不适用。

于 2013-07-28T15:40:54.973 回答