派生类能否访问基类成员取决于基类成员访问权限与继承方式的组合:public继承保持原有权限,protected继承使非private成员变为protected,private继承全变为private;构造/析构函数不继承但需显式调用;同名成员引发隐藏而非重写,需using引入基类版本。

直接说结论:派生类通过 class 派生类名 : 继承方式 基类名 语法继承基类,但能否真正访问、使用基类成员,**完全取决于基类成员的访问权限 + 继承方式的组合**,不是写了继承就自动“拿到”所有东西。
public/protected/private 继承方式怎么选
这三种方式决定基类成员在派生类内部的“可见性上限”,不是“是否继承”,而是“继承后能不能用”。
-
public继承:最常用,表达 “is-a” 关系(如Studentis-aPerson)。基类的public成员在派生类中仍是public,protected保持protected,private成员不可见 —— 这是唯一能让派生类对象外部还能当基类用的方式。 -
protected继承:基类所有非private成员在派生类中都变成protected。派生类对象不能被当作基类对象使用(比如不能隐式转换),但后续再派生的子类仍可访问这些成员。 -
private继承:基类所有非private成员在派生类中全变为private。它本质是“实现复用”,不是类型关系 ——派生类is-not-a基类,只是借了基类的代码来实现自己,连派生类自己的子类都访问不了这些继承来的成员。
基类的 private 成员到底算不算被继承
算,但你完全用不了 —— 它存在于派生类对象内存布局中(紧挨着基类其他成员),但编译器禁止你在派生类任何地方(包括成员函数)直接访问 基类::private_member。
- 错误现象:
error: 'int Base::m_private' is private within this context - 常见误操作:以为加个
using Base::m_private就能提升权限 —— 不行,using只能用于提升protected或public成员的访问级别,对private无效。 - 正确解法:如果真需要访问,基类得提供
public或protected的 getter/setter 函数,或者把成员本身改成protected。
构造函数和析构函数不被继承,但必须显式调用
派生类对象创建时,基类部分必须初始化;销毁时,基类部分也必须清理。这两步不会自动发生,必须手动干预。
立即学习“C++免费学习笔记(深入)”;
- 构造:用初始化列表调用基类构造函数,例如
Derived(int x) : Base(x) { /* ... */ }。不写的话,会尝试调用基类默认构造函数 —— 如果基类没默认构造函数,编译直接失败。 - 析构:顺序固定 —— 先调派生类析构函数,再调基类析构函数。但如果用基类指针指向派生类对象(多态场景),且基类析构函数不是
virtual,则只会调基类析构,派生类部分资源泄露。 - 关键点:只要基类可能作为多态基类被 delete,它的析构函数就必须声明为
virtual,哪怕函数体为空。
同名成员引发的隐藏(hiding)而非重写(override)
派生类里定义一个和基类同名的函数或变量,哪怕参数不同,也会导致基类版本被隐藏 —— 这不是多态,也不是重载,而是作用域屏蔽。
- 错误现象:调用
obj.func(1)报错 “no matching function”,因为编译器只在派生类作用域找func,找到同名就停,根本不去看基类有没有更匹配的重载版本。 - 解决办法:在派生类中用
using Base::func;显式把基类所有重载版本引入当前作用域。 - 注意:只有函数名相同才触发隐藏;若想实现运行时多态,必须加
virtual关键字,且函数签名(含 const 限定)必须完全一致,否则仍是隐藏。
最容易被忽略的是:继承方式和基类成员访问权限的组合效果不是直觉能猜出来的,尤其在多重继承或中间层用了 protected 继承时。与其靠记忆表格,不如写个最小测试用例,用编译器报错反推——它永远比文档诚实。


















