可可的OO:封装

引言

OOP 的三大概念,这篇文章讲的是最基本的 「封装」。

理解封装

OOP 编程最基本的概念就是封装。我们通过把函数,变量的实现细节包装成一个单一整体,向外表现 一致 的的行为的技术。

为什么要封装
  • 修改量减小,降低代码修改风险
  • 修改弹性大,内部可调整程度高
  • 提高复用性,好的封装会使类趋向于一个整体,减颗粒度

好的封装:

职能

类职能单一

一个类的功能越单一,它的职能就越纯粹,内部逻辑就越简单,可重用性就越好。语义一致性也就越强。而很多人写程序都喜欢一个 class 到底,这个 class 能处理输入,转换字符串,连接数据库 ……

函数职能单一

优点同上,而且还可以带来一个好处:异常安全

template <typename T>
class stack {
    ...
    T pop_top();
    ...
};
template <typename T>
class stack {
    ...
    T top();
    void pop();
    ...
};

是不是看起来第一种比较好呢?我当时也是这么认为的,因为我们可以写出这样的语句 int x = s.pop_top(); 而不是 int x = s.top(); s.pop();

但是你会发现,STL 库种大量使用了后一种,就是因为,在前一种情况下 不可能保证强异常安全

一旦异常发生,前一种最多只能保证 弱异常安全 即:异常会正常抛出到调用者,可能会出现脏数据,容器可能会处于一个不一致的状态。

C++ 的容器都是异常安全的

想详细了解本内容可以参考 《Exceptional C++》条款 8 - 17

成员,函数

如何衡量封装性

  • 外界看到的越多,封装性越差
  • 当修改发生时,影响越大,封装性越差

成员

将成员变量声明为 private ——《Effective C++》条款22

private成员会带来哪些好处
  • 外界看到的少了,访问成员必须通过接口
  • 通过接口,访问过程变得受限,我们可以对数据进行一致性检查等
  • 当修改发生时,我们可以通过修改接口来保证对外行为不变。

你需要做的,就是给每一个成员写上一对访问函数

而 public 与 protect 访问权限本质上是一样的, protect 并没有提供比 public 更好的封装程度。protect 其实就是 “面向子类的 private”。同样含有相同的问题。

如果你发现你的类里面充满了毫无意义的访问器,你应该看一看下一条

函数

宁以 非成员、非友元函数 替换 成员函数 ——《Effective C++》条款23

成员函数的封装性比非成员差

基于一下几个理由:

  • 同样的功能如果既可以被成员函数,也可以被非成员函数实现,非成员函数一定会通过不少于成员函数调用完成
  • 调用越多,中间层就越多,灵活性与安全性就越好
  • 成员函数的访问能力比非成员函数高

因此在 实现同样功能下请选择非成员函数

同样的,友元函数破环了封装。

struct 仅提供 POD & 值语义

本条更倾向于语义,而且更多是是个人建议与偏好

POD

C++ 中有这样的一个概念 POD

POD 这种类型十分简单,没有虚函数虚基类,最关键的是,它可以使用 memcpy() 来直接操作,这种类型没有复杂的内存结构,也没有复杂的继承链。

而 C 语言中的 struct 都是 POD,它们可以直接与系统底层进行交互,所以,我建议。所有的 POD 都应该是 struct。

值语义

struct 和 class 在 C++ 中一直是一个奇怪的存在,除了默认的访问权限不同之外,它们的表现是一样的。
对于我来说,struct 提供的是 值语义 ,而 class 是类语义

struct 提供的是 数据的聚集。 打个比方说:

struct id_card_t {
    std::string name;
    int age;
    std::string address;
};
struct Person {
public:
    std::string getName();
    int getAge();
    std::string getAddress();

     void walk();
     void saySomething(const std::string&);
     void eat();

     Person();
private:
    std::string name;
    int age;
    std::string address;
};

后面这个 Person 很显然是一个类,而不仅仅是数据的聚集。 Person 含有更多的行为,而且有可能参与继承。因此,Person 应该使用 class。

虽然以上例子中,Person 是一个 POD,但是依然不适合用 struct 来表达。

值语义比 POD 约束性更强,而且请组合 struct,不要继承

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值