优先将非成员非朋友功能发送给成员函数

时间:2011-09-21 21:41:41

标签: c++

此问题标题取自Scott Meyers的Effective C ++ 3rd Edition中第23项的标题。他使用以下代码:

class WebBrowser {
public:
    void clearCache();
    void clearHistory();
    void removeCookies();

    //This is the function in question.
    void clearEverything();
};

//Alternative non-member implementation of clearEverything() member function.
void clearBrowser(WebBrowser& wb) {
    wb.clearCache();
    wb.clearHistory();
    wb.removeCookies();
};

虽然声明下面的替代非成员非友元函数比成员函数clearEverything()更适合封装。我想部分想法是,如果提供访问的成员函数较少,则访问WebBrowser的内部成员数据的方法较少。

如果您接受此功能并制作此类外部非朋友功能的功能,您会将它们放在哪里?函数仍然与类紧密耦合,但它们将不再是类的一部分。将它们放在类的相同CPP文件中,在库中的另一个文件中,或者是什么时,这是一种好习惯吗?

我主要是来自C#背景,而且我从来没有对所有成为课堂成员的渴望摆脱那种渴望,所以这让我感到困惑(虽然听起来很傻)。

4 个答案:

答案 0 :(得分:1)

通常,您可以将它们放在关联的命名空间中。这(在某种程度上)与C#中的扩展方法有相同的功能。

问题是在C#中,如果你想制作一些静态函数,它们必须在一个类中,这是荒谬的,因为根本没有OO - 例如,Math类。在C ++中,您可以使用正确的工具来完成这项工作 - 命名空间。

答案 1 :(得分:1)

所以clearEverything是一种非常必要的便捷方法。但是由你来决定它是否合适。

这里的哲学是类定义应尽可能保持最小化,并且只提供一种方法来完成某些事情。这降低了单元测试的复杂性,交换替代实现的整个类所涉及的难度,以及可能需要被子类覆盖的函数数量。

通常,您不应该只使用一系列其他公共成员函数的公共成员函数。如果你这样做,它可能意味着:1)你的公共接口太详细/细粒度或其他不合适,被调用的函数应该是私有的,或者2)该函数应该真正在类外部。

汽车类比:喇叭通常与踩刹车一起使用,但添加一个新的踏板/按钮同时进行这两个操作是愚蠢的。结合Car.brake()Car.honk()是由Driver执行的功能。但是,如果Car.leftHeadLampOn()Car.rightHeadLampOn()是两个单独的公共方法,则可能是过度细粒度控制的示例,设计人员应重新考虑提供Driver a单Car.lightsOn()开关。

在浏览器示例中,我倾向于同意Scott Meyers的观点,即它不应该是成员函数。但是,将它放在浏览器命名空间中也可能不合适。也许最好让它成为控制Web浏览器的东西的成员,例如GUI事件处理程序的一部分。 MVC专家随时可以从这里接管。

答案 2 :(得分:0)

我做了很多。我总是把它们放在与其他类成员函数相同的.cpp中。我不认为有任何二进制大小开销取决于你放置它们的位置。 (除非你把它放在标题中:P)

答案 3 :(得分:0)

如果你想沿着这条路走下去,clearEverything的实现应该放在标题(声明)和类的实现中 - 因为它们是紧密耦合的,似乎是放置它们的最佳位置。 / p>

但是,我倾向于将它们作为课程的一部分 - 因为将来您可能还有其他事情要清除,或者可能有更好或更快的实现来实现clearEverything,例如删除数据库只是重新创建表格