You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何借助CRTP实现Base指针的Derived类型擦除以构建异构容器

解决方案

你可以通过引入非模板的公共抽象基类消除模板参数依赖,把需要多态调用的接口定义为纯虚函数,再让原来的CRTP模板类继承这个公共基类即可。

具体实现逻辑

  1. 定义无模板参数的抽象基类IBase,声明需要多态调用的接口f()为纯虚函数,同时定义虚析构函数避免内存泄漏
  2. 让原CRTP模板类Base<T>继承IBase,重写f()接口实现CRTP的静态分发
  3. 容器直接存储IBase*类型的指针即可,遍历调用时直接走普通的虚函数多态逻辑

完整可运行代码

#include <iostream>
#include <vector>

// 非模板公共抽象基类
class IBase {
public:
    virtual void f() = 0;
    virtual ~IBase() = default;
};

template<typename T>
class Base : public IBase
{
public:
    // 重写虚接口,内部走CRTP静态分发
    void f() override
    {
        static_cast<T*>(this)->f();
    }
};

class Derived1 : public Base<Derived1> {
public:
    void f()
    {
        std::cout << "Derived1::f()\n";
    }
};

class Derived2 : public Base<Derived2> {
public:
    void f()
    {
        std::cout << "Derived2::f()\n";
    }
};

int main() {
    std::vector<IBase*> vec;
    vec.push_back(new Derived1);
    vec.push_back(new Derived2);

    // 遍历容器直接调用接口,无需关心具体派生类类型
    for (auto ptr : vec) {
        ptr->f();
    }

    // 释放资源
    for (auto ptr : vec) {
        delete ptr;
    }
    vec.clear();

    return 0;
}

可选替代方案

如果你不想引入虚函数(比如要避免虚函数的运行时开销),也可以用类型擦除技术(自行封装包含调用入口的擦除层,或者直接使用std::function包装可调用对象)实现相同的效果,不过实现复杂度比继承公共基类的方案更高。


内容的提问来源于stack exchange,提问作者Eduard Rostomyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 04:45:02