C++怎么实现继承_C++OOP特性教程【深入】

虚析构函数必须显式声明,否则父类指针删除子类对象时只调用父类析构,导致子类资源未释放而崩溃或泄漏;public继承保持访问级别,对应“is-a”关系,private/protected继承改变成员对外可见性,实际应优先用组合而非private继承。

C++怎么实现继承_C++OOP特性教程【深入】

继承不是“抄代码”,而是让子类自动获得父类的成员和接口能力;没写对 publicprotected 或漏掉虚析构函数,运行时就可能崩溃或内存泄漏。

为什么子类对象一析构就崩?——虚析构函数必须显式加

父类指针指向子类对象是常见操作,比如用 std::vector<:unique_ptr>></:unique_ptr> 存多种派生类型。但若 Base 的析构函数不是 virtual,delete 时只会调用 Base::~Base(),子类自己的清理逻辑(比如释放 new 出来的资源)完全不会执行。

实操建议:

  • 只要类设计为被继承(哪怕当前没子类),析构函数必须声明为 virtual,哪怕它是空的:
    virtual ~Base() = default;
  • 不推荐写 virtual ~Base() {},因为编译器无法自动标记为 noexcept,而默认构造/析构在移动语义中常需 noexcept 保证异常安全
  • 如果类明确禁止继承,加 final 关键字更直接:
    class Leaf final : public Base { ... };

public / protected / private 继承的区别到底在哪?

不是“能不能访问”,而是“外部代码通过子类能否访问父类成员”。private 继承后,父类所有成员(包括 public 成员)在子类内部变成 privateprotected 继承则全部变成 protected;只有 public 继承才保持原有访问级别对外可见。

立即学习C++免费学习笔记(深入)”;

实操建议:

  • 99% 的业务场景只用 public 继承,它对应“is-a”关系(比如 Dog is-a Animal
  • private 继承本质是“has-a”的替代写法,但可读性差,优先用组合:
    class Dog { Animal impl_; };

    而不是

    class Dog : private Animal { };
  • protected 继承极少用,通常只出现在框架底层封装中,普通项目几乎可以忽略

子类怎么调用父类构造函数?初始化列表里写清楚

子类没有默认继承父类构造函数(C++11 后可用 using Base::Base; 继承,但有严格限制)。如果不显式调用,编译器会尝试调用父类默认构造函数;若父类没默认构造函数,直接报错:

error: no matching function for call to 'Base::Base()'

实操建议:

  • 在子类构造函数初始化列表中,第一项必须是父类构造调用:
    Derived(int x) : Base(x), member_(x * 2) {}
  • 不能在构造函数体内用 Base(x) 补救——那只是临时创建一个匿名 Base 对象,跟当前对象无关
  • 若父类构造函数是 explicit,子类调用也必须显式,否则隐式转换会被拒绝

继承链越深,对象布局越难预测;多重继承时虚基类的偏移计算、vtable 布局、RTTI 开销都会真实影响性能和调试难度。别为了“复用”硬套继承,先问一句:这个关系真的能用“is-a”说清吗?