在文章非成员函数如何改进封装中,Scott Meyers 认为没有办法阻止非成员函数“发生”。
语法问题
如果你和我讨论过这个问题的许多人一样,你可能会对我的建议的句法含义有所保留,即非朋友非成员函数应该优先于成员函数,即使你购买了我的关于封装的争论。例如,假设一个类 Wombat 支持吃饭和睡觉的功能。进一步假设吃饭功能必须实现为成员函数,而睡眠功能可以实现为成员或非朋友非成员函数。如果你按照我上面的建议,你会声明这样的事情:
class Wombat { public: void eat(double tonsToEat); void sleep(double hoursToSnooze); }; w.eat(.564); w.sleep(2.57);
啊,这一切的一致性!但是这种统一是误导性的,因为世界上的功能比你的哲学所梦想的要多。
说白了就是发生非成员函数。让我们继续以 Wombat 为例。假设您编写软件来模拟这些抓取生物,并想象您经常需要您的袋熊做的一件事就是睡半个小时。显然,您可以在代码中乱扔对 的调用
w.sleep(.5)
,但这将是很多 0.5 秒的输入时间,而且无论如何,如果这个神奇的值改变了怎么办?有很多方法可以解决这个问题,但也许最简单的方法是定义一个函数来封装您想要做的事情的细节。假设您不是 Wombat 的作者,则该函数必须是 non-member,并且您必须这样称呼它:void nap(Wombat& w) { w.sleep(.5); } Wombat w; nap(w);
你有它,你可怕的句法不一致。当你想喂你的袋熊时,你会调用成员函数,但是当你想让它们打盹时,你会调用非成员函数。
如果您稍微反思一下并对自己诚实,您就会承认您与您使用的所有重要类存在这种所谓的不一致,因为没有类具有每个客户所需的所有功能。每个客户都至少添加了一些自己的便利功能,这些功能始终是非成员的。C++ 程序员已经习惯了这一点,他们对此毫不在意。有些调用使用成员语法,有些调用使用非成员语法。人们只是查找适合他们想要调用的函数的语法,然后调用它们。生活仍在继续。它在标准 C++ 库的 STL 部分尤其如此,其中一些算法是成员函数(例如,大小),一些是非成员函数(例如,唯一),而一些是两者(例如,查找)。没有人眨眼。连你都没有。
我真的无法理解他在粗体/斜体句子中所说的话。为什么它必须以非成员身份实施?为什么不直接从 Wombat 类继承您自己的 MyWombat 类,并使nap()
函数成为 MyWombat 的成员?
我刚开始使用 C++,但这就是我在 Java 中可能会这样做的方式。这不是 C++ 的方式吗?如果不是,为什么会这样?