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

如何无需dynamic_cast或逐类实现createCopy,从基类指针创建对象副本?

问题描述

我有一个基类,还有大量继承自该基类的派生类,现在想创建对象的副本。有没有办法不用dynamic_cast,也不用在每个派生类里实现createCopy函数,就能从基类指针推导出它指向对象的实际类型?示例代码如下:

class Base {
public:
    Base(){};
    virtual ~Base() = default;
    virtual void fun() = 0;

    Base *createCopy()
    {
        return new /*some way to deduct real "this" type */
    }
};

class Derived1 : public Base
{
public:
    Derived1() : Base(){};
    virtual void fun() { /* impl */ };
};

class Derived2 : public Base
{
public:
    Derived2() : Base(){};
    virtual void fun() { /* impl */ };
};

/* Derived3 - Derived8999 implementation*/

class Derived9000 : public Base
{
public:
    Derived9000() : Base(){};
    virtual void fun() { /* impl */ };
};

int main()
{
    Base *pObj = new Derived9000; // pObj type is Derived9000*

    Base *pCopy = pObj->createCopy(); // pCopy type is Derived9000*
}
解决方案

用**CRTP(奇异递归模板模式)**就能解决这个问题,只需要做一次基类封装,所有派生类无需单独实现拷贝函数,也完全不需要使用dynamic_cast。

具体实现步骤:

  1. 在原始Base类中声明纯虚的createCopy接口
  2. 定义一个模板基类BaseCRTP,继承自Base,并在其中实现createCopy——通过模板参数获取派生类的真实类型,直接创建对应类型的副本
  3. 所有派生类继承BaseCRTP,并将自身类型作为模板参数传入

修改后的完整代码如下:

class Base {
public:
    Base() = default;
    virtual ~Base() = default;
    virtual void fun() = 0;
    // 声明纯虚拷贝接口
    virtual Base* createCopy() const = 0;
};

// CRTP模板基类,负责实现拷贝逻辑
template<typename Derived>
class BaseCRTP : public Base {
public:
    Base* createCopy() const override {
        // 利用模板参数确定真实类型,调用拷贝构造函数
        return new Derived(static_cast<const Derived&>(*this));
    }
};

// 派生类只需继承BaseCRTP并传入自身类型
class Derived1 : public BaseCRTP<Derived1> {
public:
    Derived1() = default;
    void fun() override { /* 具体实现 */ }
};

class Derived2 : public BaseCRTP<Derived2> {
public:
    Derived2() = default;
    void fun() override { /* 具体实现 */ }
};

/* Derived3 - Derived8999 都按上述方式实现 */

class Derived9000 : public BaseCRTP<Derived9000> {
public:
    Derived9000() = default;
    void fun() override { /* 具体实现 */ }
};

int main() {
    Base* pObj = new Derived9000;
    Base* pCopy = pObj->createCopy(); // pCopy实际指向Derived9000类型对象

    // 清理资源
    delete pObj;
    delete pCopy;
    return 0;
}

方案优势

  • 无重复代码:所有派生类无需编写createCopy,仅需修改继承的基类,适配几千个派生类毫无压力
  • 编译期确定类型:完全避免运行时类型转换的开销,效率更高
  • 保留多态特性:基类指针依然能正确调用对应派生类的拷贝逻辑

注意事项

  • 确保派生类拥有合适的拷贝构造函数:默认拷贝构造函数适用于简单场景,若涉及动态分配资源,需自行实现深拷贝逻辑,CRTP模板会自动调用该构造函数

内容的提问来源于stack exchange,提问作者Caboom Bom

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 06:05:19