У меня есть два тесно связанных класса, которые я назову Widget и Sprocket. В Sprocket есть набор методов, которые я хочу вызывать из Widget, но не из любого другого класса. Я также не хочу объявлять Widget другом Spocket, потому что это даст Widget доступ ко ВСЕМ защищенным и закрытым членам. Я хочу ограничить доступ Widget только к определенному набору методов.
Одно из решений, которое я придумал, - создать внутри Sprocket вложенный класс, содержащий обертки для этих методов, и сделать Widget другом этого вложенного класса. Например:
class Sprocket
{
public:
class WidgetInterface
{
friend class Widget;
WidgetInterface(Sprocket* parent) : mParent(parent) {}
private:
void A() { mParent->A(); }
void B() { mParent->B(); }
Sprocket* mParent;
};
private:
void A() { ... }
void B() { ... }
};
class Widget
{
public:
Widget(Sprocket* sprock) : mSprocketIface(sprock) {}
void doStuff() { mSprocketIface.A(); } // Widget can call Sprocket::A()
private:
Sprocket::WidgetInterface mSprocketIface;
};
Это приводит к некоторому дублированию кода, поскольку сигнатуры методов теперь объявляются в двух местах, но это работает. Но теперь предположим, что я хочу добавить подкласс Widget с именем SpecialWidget и хочу, чтобы этот класс также имел доступ к методам Sprocket. Я могу просто добавить этот новый класс в список друзей Sprocket или добавить еще один набор защищенных оболочек в Widget, к которым SpecialWidget (и любой другой подкласс) могут получить доступ, но вы можете видеть, что это становится проблемой обслуживания. Я не хочу обновлять список друзей или оболочки, если я добавляю новые классы или изменяю сигнатуру метода. Если я использую подход «добавить еще один набор оболочек», сигнатуры метода будут продублированы в трех местах!
Кто-нибудь знает более простой и понятный способ сделать это?