深入理解C++ 多态<三>(Polymorphism)模板方法模式

模板方法模式(Template Method Pattern) ,在 C++ 中常通过 非虚接口(NVI, Non-Virtual Interface) 惯用法来实现。

核心思想

  • 基类 定义一个非虚的公共成员函数 (如 process()),它内部按照固定顺序调用一系列虚函数 (通常是 protected)。

  • 派生类重写这些虚函数,提供具体实现。

  • 当通过派生类对象或基类指针/引用调用基类的非虚函数时,基类的代码被执行,但内部的虚函数调用会动态绑定到派生类的重写版本。

  • 效果:基类控制算法骨架,派生类填充细节,实现了"派生类调用基类函数,基类函数再反向多态调用派生类函数"。

详细解释

  1. 派生类调用基类函数 :例如 DerivedA a; a.process();process() 是基类的非虚函数,所以直接调用 Base::process()

  2. 基类函数多态调用派生类函数Base::process() 内部调用 step1()step2(),它们被声明为 virtual。由于 this 指向的是 DerivedA 对象,虚函数表(vtable)指向 DerivedA 的重写版本,因此实际执行 DerivedA::step1()DerivedA::step2()

  3. 好处 :基类可以强制算法流程(如先 step1step2),派生类无法改变流程,只能重写具体步骤。这符合"开闭原则"------对扩展开放(可新增派生类),对修改关闭(基类接口稳定)。

  4. 注意:在基类构造函数或析构函数中调用虚函数不会发生多态,因为此时派生类部分尚未初始化或已销毁,虚表指向基类。所以 NVI 通常用于普通成员函数

cpp 复制代码
#include <iostream>

class Base {
public:
    // 非虚公共接口,定义算法骨架
    void process() {
        std::cout << "Base::process() 开始\n";
        step1();  // 虚函数,多态调用
        step2();  // 虚函数,多态调用
        std::cout << "Base::process() 结束\n";
    }

    virtual ~Base() = default;

protected:
    // 虚函数,供派生类重写
    virtual void step1() {
        std::cout << "  Base::step1() 默认实现\n";
    }
    virtual void step2() {
        std::cout << "  Base::step2() 默认实现\n";
    }
};

class DerivedA : public Base {
protected:
    void step1() override {
        std::cout << "  DerivedA::step1() 实现\n";
    }
    void step2() override {
        std::cout << "  DerivedA::step2() 实现\n";
    }
};

class DerivedB : public Base {
protected:
    void step1() override {
        std::cout << "  DerivedB::step1() 实现\n";
    }
    // 不重写 step2,使用基类默认实现
};

int main() {
    DerivedA a;
    DerivedB b;

    std::cout << "调用 a.process():\n";
    a.process();  // 派生类对象调用基类非虚函数

    std::cout << "\n调用 b.process():\n";
    b.process();

    // 通过基类指针多态调用
    Base* p = &a;
    std::cout << "\n通过基类指针调用 p->process():\n";
    p->process();

    return 0;
}
相关推荐
君顾143 分钟前
24小时自助健身房系统开发实战:从0到1完整技术架构指南
java·开发语言·健身房
Rabitebla1 小时前
【Linux 系统编程】权限(一):身份、提权,和那 9 个权限位
linux·数据结构·c++·算法
艾莉丝努力练剑1 小时前
【AI大模型接入SDK】SQLite基础概念与C的API开发
网络·c++·人工智能·学习·架构
東隅已逝,桑榆非晚1 小时前
List(类函数学习)
c++·笔记·学习
Dr_Fourier1 小时前
AWQ量化
c++·人工智能·pytorch·ai
江屿风1 小时前
【Linux系统】【Linux 进程程序替换机制解析及自定义 Shell 核心逻辑实现 】流食般投喂
linux·运维·服务器·开发语言·笔记
SEO_juper1 小时前
2026年用Python检查多语言站点hreflang:自动揪出“回链缺失/标错语言“等致命错误(附完整代码)
开发语言·前端·seo·独立站·谷歌优化
aramae10 小时前
模拟实现strcmp()(C语言)
c语言·开发语言·后端
泡海椒11 小时前
PDF 表格样式优化:jquick-pdf 边框、圆角、背景色
java·开发语言·pdf