private继承表达“is-implemented-in-terms-of”,基类成员在派生类中全降为private,禁止隐式转换、外部访问及孙类继承;public继承表达“is-a”,保持基类访问权限并支持多态和继承链延续。

public 继承和 private 继承在 C++ 中不是“写法不同而已”,而是语义、访问控制、接口暴露程度和继承链延续性四个层面的根本差异。选错会导致编译失败、意外的不可访问、或后续派生被阻断。
基类成员在派生类中的访问权限变化
关键区别不在“能不能用”,而在“以什么权限用”:
-
public继承:基类的public成员在派生类中仍是public,protected成员仍是protected;private成员始终不可访问 -
private继承:基类所有可继承成员(即public和protected)在派生类中全部降级为private;private成员依然不可访问
这意味着:即使你在 private 派生类内部调用基类的 public 函数,它也只对该派生类自身可见——子类(孙类)无法再访问它。
派生类对象能否直接访问基类成员
这是最常踩坑的点,直接影响 API 设计:
- 用
public继承时:Derived d; d.basePublicFunc();✅ 合法,外部可调用基类公有接口 - 用
private继承时:Derived d; d.basePublicFunc();❌ 编译错误:该函数在Derived中是私有的,对外不可见
换句话说:private 继承彻底切断了“基类接口向使用者暴露”的路径,哪怕那个接口原本是 public 的。
是否支持进一步派生(继承链是否延续)
这个影响常被忽略,但对框架/库设计至关重要:
-
public派生类可以继续被其他类public或protected继承,基类public/protected成员仍可被孙类访问 -
private派生类——无论你用什么方式再继承它——其内部继承来的所有基类成员都已是private,孙类完全无法访问它们
例如:class A { public: void f(); }; → class B : private A {}; → class C : public B { void g() { f(); } }; 会编译失败,因为 f() 在 B 中是私有的,C 看不到。
什么时候该用 private 继承而不是组合
虽然多数场景推荐组合(has-a),但 private 继承仍有不可替代的用途:
- 需要访问基类的
protected成员或虚函数表布局(比如定制内存管理) - 想复用基类的
virtual函数机制,但不希望用户把派生类当作基类来用(避免隐式转换和多态滥用) - 某些模板元编程技巧中需继承以触发 SFINAE 或类型推导(如
std::tuple内部实现)
注意:private 继承后,static_cast<base>(&d) 会失败,而组合做不到这点——这种“强制隔离”正是它的设计意图。
Derived 当作 Base 来用”。一旦混淆 is-a 和 uses-a,private 继承就会变成维护噩梦。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











