不能直接访问基类私有成员,但可通过基类公有或保护成员函数间接访问;私有继承下基类public和protected成员在派生类中变为private,仍可在派生类内部访问,private成员始终不可见。

私有继承后,基类成员在派生类中是否可访问?
私有继承意味着基类的 public 和 protected 成员在派生类中全部变为 private —— 但关键点在于:它们**仍属于派生类对象的内存布局一部分**,只是访问权限被收紧。你不能在派生类外部(包括友元以外的代码)通过派生类对象调用基类的 public 成员函数,也不能在派生类外部访问继承来的 protected 成员变量。
真正能用的地方只在派生类**内部实现**中:构造函数、成员函数、友元函数里可以正常调用基类的 public 和 protected 成员(只要基类本身允许访问)。
- 基类的
private成员始终不可见,无论继承方式如何 - 派生类不能将继承来的成员“重新声明为
public”,只能通过自己新增的public成员函数间接暴露行为 - 如果基类有默认构造函数,派生类不写构造函数也能编译;但若基类只有带参构造函数,派生类必须显式调用它(在初始化列表中)
如何在派生类中调用私有继承的基类成员函数?
直接调用没问题,只要在派生类成员函数体内就行。注意:不能依赖作用域解析符从外部调用,比如 obj.Base::func() 是非法的,因为私有继承切断了“is-a”关系,也不提供这种外部访问路径。
class Base {
public:
void say() { /* ... */ }
protected:
int data = 42;
};
<p>class Derived : private Base {
public:
void expose() {
say(); // ✅ 合法:派生类内部调用继承来的 public 成员
data = 100; // ✅ 合法:派生类内部访问继承来的 protected 成员
}
};- 派生类中调用
say()不需要加Base::前缀(除非重名需消歧义) - 如果基类函数是虚函数,私有继承后依然保持虚特性,但外部无法多态调用——因为指针/引用类型无法隐式转换为基类类型
- 不要试图在
expose()外部写d.say(),这会触发编译错误:error: 'say' is inaccessible
为什么不用私有继承而改用组合?
私有继承和组合(即在派生类中声明一个基类对象作为成员)语义接近,都表达“has-a”或“is-implemented-in-terms-of”。但私有继承有两处不可忽视的副作用:
立即学习“C++免费学习笔记(深入)”;
- 它让派生类对象**占用更多内存**:即使基类无数据成员,空基类优化(EBO)在私有继承下可能失效(取决于编译器和基类是否有虚函数等)
- 它允许派生类访问基类的
protected成员,而组合做不到——除非你把基类成员设为public或加 getter,但这破坏封装 - 私有继承会使
static_cast或dynamic_cast无法从派生类指针转成基类指针,而组合完全不提供这种转换能力,反而更清晰
所以除非你需要访问基类 protected 成员,或者想复用基类的虚函数表布局(极少数底层库场景),否则优先用组合。
私有继承下如何让外部使用部分功能?
唯一合规方式是:在派生类中定义新的 public 成员函数,内部转发调用基类成员。这不是“暴露继承”,而是“封装实现细节”。
class Derived : private Base {
public:
void speak() { say(); } // ✅ 安全暴露接口
int get_data() const { return data; } // ✅ 封装对 protected 成员的访问
};- 别在派生类中用
using Base::say;—— 这在私有继承下无效,会报错:error: using-declaration for non-public member - 如果基类有多个重载函数,且你想只暴露其中几个,必须手动写转发函数,无法批量导入
- 返回类型或参数涉及基类类型时要小心:比如
Base& get_base()不行,因为Base对外部不可见;但返回void或基本类型就没事
私有继承真正难的不是语法,而是判断“是否真需要它”——多数时候,组合 + 公共接口封装更直白、更易维护、更不容易误用。


















