条款 23:宁以 non-member、non-friend 替换 member 函数
核心思想
-
更高的封装性
non-member
函数不需要访问类的 private 或 protected 成员,减少对类实现的依赖,增强封装性。
-
更灵活的设计
- 将功能从类内部移到类外部,功能模块更容易独立扩展,减少类的复杂性。
-
更强的可扩展性
non-member
函数可以与类的接口分离,使得类的使用更灵活,同时保留对类行为的控制。
-
使用命名空间组织代码
- 将
non-member
函数与相关类放在同一命名空间中,有助于逻辑关联性和代码可读性。
- 将
示例代码
namespace WebBrowserStuff {class WebBrowser { public:void navigateTo(const std::string& url) {// 导航到指定 URLcurrentUrl_ = url;}void display() const {std::cout << "Displaying: " << currentUrl_ << std::endl;} private:std::string currentUrl_; // 当前网址 };// non-member 函数,清理浏览器 void clearBrowser(WebBrowser& wb) {wb.navigateTo("about:blank");std::cout << "Browser cleared." << std::endl; }} // namespace WebBrowserStuff
注意事项
-
非成员函数增强封装性
- 非成员函数无法访问类的 private 和 protected 成员,促使接口设计更具一致性和清晰性。
-
避免滥用 friend 函数
class WebBrowser { public:friend void clearBrowser(WebBrowser& wb); // 不推荐:滥用 friend };
- 问题:friend 函数打破封装性,导致外部函数能直接访问类的私有成员。
- 改进:尽量设计为非成员函数,避免直接访问类的内部实现。
-
使用命名空间组织代码
- 将
non-member
函数与其操作的类放在同一个命名空间,确保逻辑清晰。
namespace WebBrowserStuff {class WebBrowser {...};void clearBrowser(WebBrowser& wb); // non-member 函数 }
- 将