我已经实现了我的课程,可以使用标准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)
,并使该friend
为A
。
请注意,使用这种方法,AImpl
不必限制访问。无论如何,它的字段和大小只能从A.cpp
获得。但是,如果要将AImpl
的内部元素设为private
,则也可以将ostream &operator <<(ostream &os, const A &obj)
设置为fried
的AImpl
。
/* 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;
...
}