Effective C++ (E3 22、23)笔记之成员变量声明为private、以非成员非友元函数替代成员函数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/brahmsjiang/article/details/79155342

成员变量就应该是private。
理由一:语法一致性。对客户而言每样东西都是函数。
理由二:可通过成员函数严格控制其读写权限、添加约束条件
根本理由:封装性
声明为private则客户只能通过函数接口访问,客户不用关心实现方法,这为“所有可能实现”提供了弹性。并且以接口替代直接对变量的访问,从代码破坏量来说,前者将远远小于后者。客户很可能只需重新编译,甚至可以消除重新编译(条款31)。

然后记得,protected并不比public更具封装性。public变量将影响所有客户码,而protected变量将影响所有继承类。



尽管成员函数可以提高封装性,这里却有一个反直观的结论。有个浏览器类,有各种清理缓存的方法:

class WebBrowser
{
public:
	void clearCache();
	void clearHistory();
	void clearBookmarks();
	void clearCookies();
};

为了客户方便清理所有缓存,提供一个便利函数,调用所有清理方法:

void clearBrowser(WebBrowser& wb)
{
	wb.clearCache();
	wb.clearHistory();
	wb.clearBookmarks();
	wb.clearCookies();
}

那么此便利函数是该定义为成员,还是非成员函数呢?

答案是以非成员、非友元函数替代成员函数

对于一个成员变量,我们以”能够访问其的函数数量“作为丈量其封装性的依据。对于一个成员变量,我们以”能够访问其的函数数量“作为丈量其封装性的依据。即能够访问的函数越多,封装性越差。而友元和成员函数具有相同权限,对封装型造成的冲击是一样的,因此也不予考虑。

对于一个成员变量,我们以”能够访问其的函数数量“作为丈量其封装性的依据。即能够访问的函数越多,封装性越差。而友元和成员函数具有相同权限,对封装型造成的冲击是一样的,因此也不予考虑。


对于非成员函数clearBrowser,比较自然做法是将其和WebBrowser置于同一namespace内:


namespace WebBrowserStuff{
class WebBrowser	
{
public:
	void clearCache();
	void clearHistory();
	void clearBookmarks();
	void clearCookies();
};


void clearBrowser(WebBrowser& wb);
	
}


便利函数只是方便客户实现特定机能,像WebBrowser这个类可能具有大量的便利函数。由于命名空间可以跨越多个文件但单个类做不到,因此可以将不同的便利函数声明于不同的头文件中。用户想使用特定机能只需包含某个头文件而已,这允许客户只对他们所用的那部分系统形成编译相依,而这正是STL库的组织方式(以分散头文件定义std namespace):

//webbrowser.h
namespace WebBrowserStuff{
class WebBrowser
{
//核心机能
};

void clearBrowser(WebBrowser& wb);	//公共便利函数
}
//webbrowserbookmarks.h

namespace WebBrowserStuff{

class WebBrowser;
void clear_Bookmarks(WebBrowser& wb); 
}
//webbrowsercookies.h

namespace WebBrowserStuff{

class WebBrowser;
void clear_Cookies(WebBrowser& wb);

}
注意,定义命名空间内的函数时也要放在namespace内(须包含webbrowser.h,因为调用webbrowser函数需要看到完整定义式):

#include "webbrowser.h"
#include "webbrowserbookmarks.h"

using namespace std;

namespace WebBrowserStuff{

void clear_Bookmarks(WebBrowser& wb)
{
	wb.clearBookmarks();
}
}


用户想要扩充便利函数也非常容易,只需另加头文件,并将函数声明置于其中,包裹在WebBrowserStuff命名空间即可。当然核心类WebBrowser对客户是不可扩展的。

综上,以非成员非友元函数替换成员函数能够增加封装性、包裹弹性和机能扩充性


展开阅读全文

没有更多推荐了,返回首页