Effective C++ 条款22、23

条款22 将成员变量声明为private

此条款解决的问题,为什么成员变量不该是public,然后所有反对public成员变量的论点同样适用于protected成员变量。于是成员变应该是private。

理由一:语法一致性,public全为成员函数,private全为成员变量(看起来就舒服,调用起来(统一都要加个函数调用符)肯定也舒服,哈哈!)

理由二:以函数取得或设定其值,即可实现“不准访问”、“只读访问”、“读写访问”、“只写访问”,也即——可细微划分访问控制权。如下举例:

class AccessLevels {
public:
	int getReadOnly()const { return readOnly; }
	void setReadWrite(int value) { readWrite = value; }
	int getReadWrite()const { return readWrite; }
	void setWriteOnly(int value) { writeOnly = value; }
private:
	int noAccess;
	int readOnly;
	int readWrite;
	int writeOnly;
};

理由三:封装,其好处是“为所有可能的实现”提供弹性,确保class的约束是会获得维护,只有成员函数能影响成员变量。不封装意味不可以改变。

protected并不比public更具有封装性

有一个public成员变量,如果取消此变量,则所有使用它的客户码都会被破坏,而那是一个不可知的大量。因此public成员变量完全没有封装性。假设一个protected成员变量,最终取消此变量,则所有使用它的derived classes都会被破坏,而那往往也是一个不可知的大量。因此,protected成员变量就像public成员变量一样缺乏封装性。

一旦将一个成员变量声明为public或protected而客户开始使用它,就很难改变那个成员变量所涉及的一切。于是太多代码需要重写、重新测试、重新编写文档、重新编译。从封装的角度出发,其实只有两种访问权限:private(提供封装 )和其他(不提供封装)。

条款23 宁以non-member、non-friend替换menber函数

如果某些东西被封装,它就不再可见。愈多东西被封装,愈少人可以看到它。而愈少人看到它,我们就有愈大的弹性去变化它,因国我们的改变仅仅直接影响看到改变的那些人事特。因此,愈多东西被封装,我们改变那些东西的能力也就愈大。推崇封装的原因:它使我们能够改变事物而只影响有限客户。

衡量数据封装性的粗糙尺度:计算能够访问private数据的函数数量,愈多函数能访问,数据封装性越差。

于是,non-member、non-friend函数比member函数产生更大的封装性。

以下举一实例:

class WebBrowser {
public:
	void clearCache();
	void clearHistory();
	void removeCookies();
};
//有一个成员函数统一执行上述所有这些动作,于是见如下
class WebBrowser {
public:
	void clearEverything();//调用clearCache,clearHistory,removeCookies
};

//以一个non-member函数调用适当的menber函数
void clearBrowser(WebBrowser& wb) {//哈哈,关注封装性而让函数成为class WebBrowser类的non-member
	wb.clearCache();
	wb.clearHistory();
	wb.removeCookies();
}

上述void clearBrowser();是一个non-member函数,这点很好,完美实现前面所讲的封装性问题。但问题又来了,如别的class也需要存在一个clearBrowser非成员函数,那就造成了名字冲突。解决办法:使用命名空间

namespace WebBroserStuff {
	class WebBrowser{};
	void clearBrowser(WebBroser& wb);
}

namespace与class不同,前者跨越多个源码文件而后者不能。

假设一个像WebBrowser这样的class可能拥有大量便 利函数,某些与书签有关,某些与打印有关,还有一些与cookie有管理有关......通常我们只对其中一个或某些感兴趣。分离它们的最直接做法就是将书签相关便利函数声明于一个头文件,将cookie相关便利函数声时于另一个头文件,再将打印相关便利函数声明于第三个头文件,与此类推。

//头文件“webbrowser.h”—— 这个头文件针对class WebBrowser自身及WebBrowser核心机能
namespace WebBroserStuff {
	class WebBrowser {};
	/*核心机能的实现,例如几乎所有客户都需要的non-member函数*/
}

//头文件“webbrowserbookmark.h”
namespace WebBroserStuff {
	/*与书签相关的便利函数*/
}

//头文件“webbrowsercookies.h”
namespace WebBroserStuff {
	/*与cookies相关的便利函数*/
}

这正是C++标准程序库的组织方式。STL并不是拥有单一、整体、庞大的<C++StandardLibrary>头文件并在其中内含std命名空间内的每一样东西,而是有数个十个头文件(<vector>,<algorithm>,<memory>等等),每个头文件声明std的某些机能。

将所有便利函数放在多个头文件内但隶属同一个命名空间,意味客户可以轻松扩展这一组便利函数。客户只需要做的就是添加更多non-member non-friend函数到些命名空间内。

以上内容均来自Scott Meyers大师所著Effective C++ version3,如有错误地方,欢迎指正!相互学习,促进!!

猜你喜欢

转载自blog.csdn.net/tt_love9527/article/details/80522077