zoukankan      html  css  js  c++  java
  • 第十三篇:成员函数与非成员函数的选择

    前言

           相信很多使用C++语言的人都有这么一种错误的观点 - 除了主函数,其他函数都应当声明为某个类的成员函数,以实现封装性。

           这种观点错在哪里?我们又该如何在成员函数与非成员函数之间进行选择呢?

           针对这个问题,本文将给出一种非常科学的解决方案。

    问题分析

           假定有一个网页浏览器类,其中有用来清除缓存,清除浏览记录,清除cookies的成员函数:

    1 class WebBrowser
    2 {
    3 public:
    4     // ......
    5     void clearCache();    // 清除缓存
    6     void clearHistory();    // 清除浏览记录
    7     void removeCookies();    // 清除cookies
    8     // ......
    9 };

           相信有很多用户希望能够一次执行完所有的这些函数。

           故也许你会做出这样的设计:

     1 class WebBrowser
     2 {
     3 public:
     4     // ......
     5     void clearEverything();    // 这个函数包含下面三个函数
     6     void clearCache();    // 清除缓存
     7     void clearHistory();    // 清除浏览记录
     8     void removeCookies();    // 清除cookies
     9     // ......
    10 };

           但更有经验的程序员会用非成员函数实现此功能:

    1 // 非成员函数
    2 void clearBrowser(WebBrowser & wb)
    3 {
    4     wb.clearCache();
    5     wb.clearHistory();
    6     wb.removeCookies();
    7 }

           下面来分析这两种做法:

           某个功能用成员函数来实现的话,对象中的变量将对该函数彻底开放,同时会将对象中的数据更大程度的暴露出来,尤其是随着开发的进行你会设置非常非常多的成员函数,到时你都搞不清哪些数据是封闭的哪些是可供用户操纵的。

           故这样的做法很大程度上其实是破坏了封装性,应当采用下面这种做法。

           也许你会抱怨,如果设置为非成员函数,那到时一堆非成员函数,代码岂非乱成一团?

           那么你就需要好好学习下 - C++中非成员函数的使用方法了。

    C++中非成员函数的使用方法

           还是接着上面这个例子。

           随着开发的进展,这个浏览器的类中会增加与书签有关的操作,与cookies相关的操作。。。。。。这种情况下,科学的做法是:

           1. 浏览器类中仅仅包含最核心的一部分函数 - 也即所有的用户都需要的。

           2. 对于书签与cookies相关操作,分别建立各自的.h,.cpp文件。

           3. 将1,2中的所有头文件都囊括进一个namespace。这里设置namespace的目的就是为了防止非成员函数重名。关于namespace的相关说明请查阅相关文档。

           具体实现可参考以下代码:

     1 // webbrowser.h
     2 namespace WebBrowserStuff {
     3 
     4     class WebBrowser
     5     {
     6         // ......
     7         // 仅定义该类最核心的功能
     8         // ......
     9     };
    10 
    11     // 定义核心非成员函数
    12 }
    13 
    14 // webbrowserbookmarks.h
    15 namespace WebBrowserStuff {
    16 
    17     // 定义与书签有关的非成员函数
    18 
    19 }
    20 
    21 // webbrowsercookies.h
    22 namespace WebBrowserStuff {
    23 
    24     // 定义与cookies有关的非成员函数
    25 
    26 }

           对于类的使用者来说,需要哪方面功能就 #include 哪个头文件,非常方便。

    小结

           如今一些大型类库,比如标准类库,OpenCV,都是这样的组成及使用方式。

           以后的文章中会告诉你如何将你自己实现的模块封装成dll,供其他人使用,就像OpenCV OpenGL等知名类库一样,敬请期待:)

  • 相关阅读:
    使用 Python 编码和解码 JSON 对象
    搞定github下载加速
    git错误:fatal: Could not read from remote repository.解决
    webstorm安装配置
    node.js下载安装
    IDEA安装小配置
    JAVA软件安装
    关于升级一般软件的一些想法
    linux 的 逻辑卷管理
    记一次内核升级。
  • 原文地址:https://www.cnblogs.com/muchen/p/6353793.html
Copyright © 2011-2022 走看看