我已经实现了我的课程,可以使用标准PIMPL习惯用语来说课程A。当我尝试为实现类<<重载AImpl运算符时出现问题

/* A.h */
class A {
public:
     ...
private:
     class AImpl;
     AImpl *impl;
}
/* Aimpl.h */
class AImpl {
     ...
     friend ostream &operator <<(ostream &os, const AImpl &impl);
     ...
}
/* elsewhere.cpp */
ostream &operator <<(ostream &os, const AImpl &impl) {
     ...
}


问题源于重载的操作员无法访问AImpl类,该类在A中声明为私有。
现在,我在如何解决此问题上处于两难境地。一种方法是也声明类A的重载运算符。另一种方法是公开类AImpl的私有声明。
哪种方法更好,更安全?

最佳答案

恕我直言,您滥用PIMPL习惯用语。这个习惯用法要求实现是真正私有的,也就是说,AImpl不应在头文件中定义(供大家查看),而应该在A.cpp运算符所属的<<中定义。

如果您这样做<<运算符也没有必要在头文件中声明,那么访问PIMPL的唯一方法就是通过包含类。您应改为定义ostream &operator <<(ostream &os, const A &obj),并使该friendA

请注意,使用这种方法,AImpl不必限制访问。无论如何,它的字段和大小只能从A.cpp获得。但是,如果要将AImpl的内部元素设为private,则也可以将ostream &operator <<(ostream &os, const A &obj)设置为friedAImpl

/* A.h */
class A {
public:
     ...
private:
     class AImpl;
     AImpl *impl;

     friend ostream &operator <<(ostream &os, const A &obj);
}

/* A.cpp */
class AImpl {
public:
     // OR:
     friend ostream &operator <<(ostream &os, const A &obj);

     ...
}

ostream &operator <<(ostream &os, const A &obj) {
     AImpl* impl = obj.impl;
     ...
}

09-06 19:27