c++子类默认继承父类public成员函数,但private不继承、protected仅限类内调用;继承须用public方式,析构函数需virtual以防资源泄漏;子类可显式调用base::func()扩展逻辑,同名函数会隐藏而非重载,需using引入或override确保正确覆盖。

子类定义时怎么写才能真正继承父类方法
不加任何修饰,C++ 子类默认就继承 public 成员函数——但仅限访问权限允许的那些。关键不是“能不能写”,而是“能不能用”。private 方法不会被继承,protected 方法能继承但不能在类外调用,只有 public 方法才对子类对象开放。
常见错误现象:error: 'func' is a private member of 'Base',明明父类有这个函数,子类却调不到——八成是父类声明成了 private 或 protected,而子类又试图在外部直接调用。
- 继承方式必须明确:用
: public Base(推荐),而不是: Base(默认private继承,会导致所有继承来的方法变private) - 父类方法若带
virtual,子类重写需加override,否则可能静默不覆盖 - 构造函数不继承,子类必须自己定义,并显式调用父类构造:用初始化列表写
Derived() : Base(arg) {}
父类析构函数没加 virtual 会出什么问题
这是 C++ 继承里最隐蔽也最危险的坑:如果父类指针指向子类对象,删除时只调父类析构,子类独有的资源(比如 new 出来的内存、打开的文件句柄)根本不会释放。
典型错误现象:程序跑完没报错,但 valgrind 显示内存泄漏;或者子类析构里打了日志,结果完全没输出。
立即学习“C++免费学习笔记(深入)”;
- 只要类可能作为基类被继承,析构函数必须声明为
virtual - 不需要手动实现空体,写
virtual ~Base() = default;就够了 - 一旦加了
virtual,整个继承链的析构调用顺序就是从派生到基类,安全可靠
子类想扩展父类方法,但又不想完全重写
不是非得二选一:全用父类逻辑,或全自己重写。C++ 支持在子类方法里显式调父类版本,实现“先做父类的事,再加点自己的”。
使用场景:比如父类 save() 把数据写进缓冲区,子类想在此基础上额外写入时间戳,或者发个通知。
- 语法很简单:
Base::save();—— 注意作用域解析符,不能漏Base:: - 只能在子类成员函数内部调,不能在全局或静态函数里用
- 如果父类方法是
virtual,这里调的仍是父类原始实现,不会触发多态跳转 - 别在构造/析构函数里这么干:虚函数机制此时未完全建立或已开始销毁
继承后发现函数调用不符合预期,怎么快速定位是不是重载/隐藏搞错了
C++ 不是 Java,子类函数名只要和父类一样,哪怕参数不同,也会隐藏(hide)整个父类同名函数族,而不是像 Java 那样自动构成重载(overload)。
错误现象:obj.func(1); 编译失败,提示 “no matching function”,但明明父类有个 func(int) —— 很可能是子类定义了 func(double),把父类所有 func 都遮住了。
- 用
using Base::func;在子类里把父类同名函数引入作用域,就能恢复重载行为 - 编译器不会警告这种隐藏,除非开启
-Woverloaded-virtual(GCC/Clang) - 如果真想重写某个虚函数,务必加
override,编译器会检查签名是否完全匹配,避免拼写或 const 差异导致意外隐藏
继承本身不难,难的是每个细节都牵扯到对象布局、调用决议、生命周期这些底层机制。稍微松懈,bug 就藏在看似正常的调用背后。











