侧边栏壁纸
博主头像
如此肤浅

但行好事,莫问前程!

  • 累计撰写 52 篇文章
  • 累计创建 6 个标签
  • 累计收到 6 条评论

目 录CONTENT

文章目录

条款39 明智而审慎地使用 private 继承

如此肤浅
2022-06-08 / 2 评论 / 0 点赞 / 71 阅读 / 1,156 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-06-08,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

1. Private 继承意味 is-implemented-in-terms of(根据某物实现出)。它通常比复合(composition)的级别低。但是当 derived class 需要访问 protected base class 的成员,或需要重新定义继承而来的 virtual 函数时,这么设计是合理的。
2. 和复合(composition)不同,private 继承可以造成 empty base 最优化。这对致力于“对象尺寸最小化”的程序库开发者而言,可能很重要。

条款32中提到将 public 继承视为 is-a 关系。在那个例子中我们有个继承体系,其中 class student 以 public 形式继承 class Person,于是编译器在必要时刻(为了让函数调用成功)将 students 暗自转换为 Persons。现在我再重复该例的一部分,并以 private 继承替换 public 继承:

class Person { ... };
class Student: private Person { ... }; // 改为private继承
void eat(const Person& p);
void study(const Student& s);

Person p;
Student s;

eat(p); // 没问题,p是人,会吃
eat(s); // 错误!无法执行

显然 private 继承不是 is-a 关系!!!

如果类 D 以 private 形式继承类 B,意思是 D 的对象根据 B 的对象实现而得。Pirvate 继承意味着 is-implement-in-terms-of(根据某物实现出),与条款38中复合(composition)的意义相同。但请尽可能使用复合,必要时才使用 private 继承。那何时使用 private 呢?

场景

假设现在需要周期性地统计 Widget class 中某些数据的信息,因此需要某种定时器来收集信息。为了尽可能地复用代码,设计了一个 Timer class:

class Timer {
public:
	explicit Timer(int tickFrequency);
    // 每个周期结束该函数被自动调用一次
    virtual void onTick() const;
    ...
};

我们可以重新定义这个 virtual 函数,让它取出 Widget 中数据的信息。为了让 Widget 重新定义 Timer 内的 virtual 函数,Widget 必须继承自 Timer。但 public 继承在此例并不适当,因为 Widget 并不是个 Timer,如果使用 public 继承很容易造成不正确地使用 Widget 接口,违反了条款18。

我们以 private 形式继承 Timer:

class Widget: private Timer {
private:
	virtual void onTick() const; // 获取Widget的数据信息
    ...
};

后面没看懂

0

评论区