C++ 中的继承:public、private、protected 与性能

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C++ 继承修饰符背后隐藏着什么?

\n\n

想象一下,您是一位建筑师。您有一张“建筑”蓝图(基类),并希望根据它建造三栋不同的“房子”(派生类)。一栋房子是精确的复制品,带有公共入口(public);第二栋带有封闭的内院(private);第三栋则只允许家人和朋友进入(protected)。在 C++ 中,继承修饰符正是这样工作的。但是,这种选择会影响程序的运行速度吗?剧透:既会,也不会。让我们来弄清楚如何避免搬起石头砸自己的脚,同时还能优化代码。

\n\n

这个问题是 Stack Overflow 上最热门的问题之一(有数万次浏览),这并非没有原因。新手经常混淆类成员的访问级别和继承类型。而有经验的开发者知道:正确选择继承方式可以节省数小时的调试时间,甚至能略微提升程序速度。今天,在 pythonlib.ru 上,我们将一劳永逸地解决这个问题。

\n\n

继承三角:public、private、protected

\n\n

首先,基础知识。假设我们有一个基类 Animal:

\n\n
class Animal {\npublic:\n    void eat() { /* ... */ }\nprotected:\n    int age;\nprivate:\n    std::string secretDNA;\n};
\n\n

现在,让我们看看三种继承类型如何改变派生类 Dog 对这些成员的访问权限。

\n\n

1. Public 继承 — “原样保留”

\n

这是最常见且最直观的类型。所有访问级别保持不变:

\n
    \n
  • public → public(对所有代码可见)
  • \n
  • protected → protected(对派生类可见)
  • \n
  • private → 不可访问(保留在基类中)
  • \n
\n

当您想表达 "Dog IS-A Animal" 的关系时使用。这是经典的 OOP。

\n\n

2. Protected 继承 — “仅限内部使用”

\n

基类的所有 public 成员在派生类中变为 protected:

\n
    \n
  • public → protected
  • \n
  • protected → protected
  • \n
  • private → 不可访问
  • \n
\n

当您想对外部世界隐藏实现细节,但允许“孙子类”访问时使用。例如,Boost 库在其内部机制中积极使用 protected 继承。

\n\n

3. Private 继承 — “我的,只属于我的”

\n

这是最严格的模式。所有 public 和 protected 成员都变为 private:

\n
    \n
  • public → private
  • \n
  • protected → private
  • \n
  • private → 不可访问
  • \n
\n

这表示 "Dog 是通过 Animal 实现的" 关系。它常被用来替代组合以实现优化(详见下文)。

\n\n

性能:关键点在哪里?

\n\n

现在,我们来看看这个引人入胜的核心问题:继承类型会影响性能吗?简而言之:直接来说,不会;但间接来说,非常会。

\n\n

误区:private 继承比 public 更快

\n

有些人认为 private 继承“消除了多余的检查”。这是错误的。访问修饰符(public、protected、private)是纯粹的编译期概念。编译器在构建阶段检查它们,并生成相同的机器码。运行时没有区别。

\n\n

现实:通过空基类优化 (EBO) 实现优化

\n

这才是 private 继承真正能加速程序的地方!如果基类不包含任何数据(空类),那么在 public 或 protected 继承下,编译器可能(但不是必须)会添加一个额外的字节用于对齐。而在 private 继承下,空基类优化 (Empty Base Optimization) 会生效。

博客

书籍推荐