我有两个密切相关的类,我称之为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;
};
这导致一些代码重复,因为方法签名现在在两个地方声明,但它可以工作。但现在假设我想添加一个名为SpecialWidget的Widget的子类,我希望该类也可以访问Sprocket方法。我可以简单地将这个新类添加到Sprocket好友列表中,或者我可以在Widget中添加另一组受保护的包装器,SpecialWidget(和任何其他子类)可以访问但是你可以看到这现在成为一个维护问题。如果我添加新类或更改方法签名,我不想更新好友列表或包装器。如果我使用“添加另一套包装”方法,方法签名将在三个地方重复!
有人知道更简单,更清洁的方法吗?
答案 0 :(得分:2)
如果你有两个紧密耦合的类,那么真的不值得尝试使friend
访问更细粒度。你可以控制两者的实现,你应该相信自己,不要滥用调用一些你不需要调用的方法的能力。严格来说,需要调用。
如果你想明确未来的代码维护者,请在friend
声明中添加注释,解释它为什么存在(一般来说是个好主意),以及允许哪些私有方法被调用。朋友班。
答案 1 :(得分:1)
Sprocket有一组方法我想从Widget调用,但不能从任何其他类调用。
为什么不为自己省点麻烦呢?在Widget
中实现这组方法,可能在这些方法中添加一个Sprocket参数?
答案 2 :(得分:1)
我会将WidgetInterface实现为Sprocket继承的真实接口,因此A和B都是Widget所知道的。好吧,其他人也可以使用该界面,但他们可能有理由这样做。
答案 3 :(得分:0)
秘密是所有这些访问控制都是毫无意义和虚幻的,并且没有办法真正限制任何访问任何东西。你只是让事情复杂化,并且很难弄清楚哪些部分的小部件可以使用以及哪些部分没有。相反,使widget和sprocket的界面更加明显,并且可能让widget拥有一个私有链轮。如果人们如此无能,以至于他们会违反这一点,就没有任何帮助,但是如果你做了一些令人憎恶的事情并且很难弄明白,那么即使是那些熟悉C ++的人也无法轻易使用它。