Я реализовал свой класс, скажем, класс A
используя стандартную идиому PIMPL.
Проблема возникает, когда я пытаюсь перегрузить <<
оператор для моего класса реализации 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;
...
}
Других решений пока нет …