Effective C++读书笔记——item23(用非成员,非友元函数取代成员函数)

一、主要观点

  • 在某些情况下,使用 non-membernon-friend 函数来替换 member 函数可以增强封装性和可扩展性,提供更好的软件设计。

二、详细解释

  1. 封装性

    • 类成员函数的封装性考量 :成员函数可以访问类的 private 成员,这在一定程度上破坏了封装性。因为它拥有比实际所需更多的对类内部的访问权限。例如,对于一个类 Widget 的成员函数,它可以访问类的所有 private 数据成员和函数,即使某些数据或函数并不需要被该成员函数操作。
    • non-member、non-friend 函数的优势 :non-member、non-friend 函数只能通过类的 public 接口来访问类,这意味着它们不能直接访问类的 private 成员。这种方式可以将类的内部实现细节更好地隐藏起来,增强封装性。例如,对于一个处理 Widget 类对象的 non-membernon-friend 函数,它只能通过 Widget 类的 public 接口进行操作,不能访问 Widget 类内部的 private 成员,这样类的内部实现可以更加自由地修改而不影响这个外部函数。
  2. 可扩展性

    • 对类功能的扩展更灵活 :使用 non-member、non-friend 函数可以将不同的功能分布在不同的函数中,而不是将所有功能都集中在类的成员函数里。这样,当需要对类的功能进行扩展时,可以方便地添加新的 non-membernon-friend 函数,而不需要修改类的内部实现。
    • 命名空间的使用 :可以将相关的 non-member、non-friend 函数放在一个命名空间中,形成一个功能集合。这样可以更好地组织代码,并且可以根据不同的功能模块将函数分类到不同的命名空间中,方便代码的管理和维护。例如:
    cpp 复制代码
    namespace WidgetStuff {
        class Widget {... };
        void doSomething(Widget& w);
        void doAnotherThing(Widget& w);
    }

    这里,doSomethingdoAnotherThingnon-membernon-friend 函数,它们通过 Widgetpublic 接口操作 Widget 类,当需要添加新的操作 Widget 的函数时,只需在 WidgetStuff 命名空间中添加即可,而不用修改 Widget 类。

  3. 编译依赖关系

    • 减少依赖member 函数的修改通常会导致类的重新编译,因为它是类定义的一部分。而 non-membernon-friend 函数的修改通常只需要重新编译该函数本身,减少了对类的依赖。这在大型项目中可以提高编译速度。
    • 降低耦合non-membernon-friend 函数与类的耦合度相对较低,使得类的接口更加稳定,避免因修改函数而影响类的内部实现和其他使用该类的代码。
  4. 示例说明

    • 考虑一个表示网页浏览器的类 WebBrowser,可能有清除缓存、清除历史记录、清除 Cookies 等操作。可以有两种实现方式:
    cpp 复制代码
    class WebBrowser {
    public:
        void clearCache();
        void clearHistory();
        void clearCookies();
        void clearEverything() {  // member function
            clearCache();
            clearHistory();
            clearCookies();
        }
    };

    或者使用 non-membernon-friend 函数:

    cpp 复制代码
    class WebBrowser {
    public:
        void clearCache();
        void clearHistory();
        void clearCookies();
    };
    
    void clearEverything(WebBrowser& wb) {  // non-member, non-friend function
        wb.clearCache();
        wb.clearHistory();
        wb.clearCookies();
    }

    在这个例子中,使用 non-membernon-friend 函数 clearEverything 可以将清除操作的功能与 WebBrowser 类分离,避免 WebBrowser 类变得臃肿,同时也不会增加 WebBrowser 类的封装性负担,因为 clearEverything 函数无法访问 WebBrowser 类的 private 成员。

三、总结

  • 为了实现更好的封装性、可扩展性、降低编译依赖和降低耦合度,在某些情况下,应该优先考虑使用 non-membernon-friend 函数而不是 member 函数。这有助于将类的功能分离,提高代码的可维护性和组织性,同时使类的内部实现更加独立和灵活。
相关推荐
Icomi_12 分钟前
【PyTorch】3.张量类型转换
c语言·c++·人工智能·pytorch·python·深度学习·神经网络
hy____12317 分钟前
C语言:数据的存储
c语言·开发语言
prettyxian23 分钟前
【c++】vector的使用
开发语言·c++
GISer Liu1 小时前
深入理解Transformer中的解码器原理(Decoder)与掩码机制
开发语言·人工智能·python·深度学习·机器学习·llm·transformer
PaLu-LI1 小时前
ORB-SLAM2源码学习:Initializer.cc(11): Initializer::ReconstructH用H矩阵恢复R, t和三维点
c++·人工智能·学习·ubuntu·计算机视觉·矩阵
TANGLONG2221 小时前
【C++】类与对象初级应用篇:打造自定义日期类与日期计算器(2w5k字长文附源码)
java·c语言·开发语言·c++·python·面试·跳槽
重生之我在20年代敲代码1 小时前
【C++】string类使用详解
c++·笔记
martian6651 小时前
第23篇:Python开发进阶:详解测试驱动开发(TDD)
开发语言·驱动开发·python·tdd
xianwu5432 小时前
反向代理模块1
开发语言·网络·数据库·c++·mysql
夏子曦2 小时前
Python+OpenCV(1)---傅里叶变换
开发语言·python·opencv