如果您为 B 重载了朋友 operator<<,您可以为 D 调用该运算符,即使它不是 D 的朋友:
class B {
public:
B(int i=0):v(i){}
private:
int v;
friend ostream& operator<< (ostream& os, const B& b);
};
class D:public B {
public:
D(string s=""s,int i=1) : B(i),v2(s){}
private:
string v2;
};
// access to the private members of B. B is accessed via a reference.
ostream& operator<< (ostream& os, const B& b){
return os<<b.v;
}
int main() {
B b;
D d;
cout << b <<endl; // calls operator<< for B
cout << d <<endl; // calls operator<< for the B sub-object of D
}
Online demo
对于D 对象,使用D 的B 主题,因为我上面的代码通过引用传递参数。如果重载将通过值而不是通过引用传递参数,它也可以工作,但 d 对象将被切片为 B 对象。
在这两种情况下,都会调用父类的运算符重载。
您也可以为子类重载运算符。但是由于友谊不是继承的,如果您需要访问私人成员,则需要定义一个新的友谊:
ostream& operator<< (ostream& os, const D& d){
//return os<<d.v<<d.v2; // not alloewed because D has no visibility on B's private members
return os << *static_cast<const B*>(&d) << d.v2;
}
Demo
D 的友谊仅限于 D 的私人成员,并且不能访问 B 的私人成员。通常的方法是调用 B 的重载(这里通过转换技巧),并访问 D 的私有成员。
当然,如果 operator<< 只访问公共成员,我们就不需要任何 freindshop 来处理重载。