欢迎光临
我们一直在努力

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

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

核心思想

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

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

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

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

详细解释

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

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

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

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

  • #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;
    }

    赞(0)
    未经允许不得转载:171主机测评 » 深入理解C++ 多态<三>(Polymorphism)模板方法模式
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址