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

如何在基类方法中获取派生类的sizeof(*this)与decltype(*this)?

首先,你的理解完全正确——如果不在每个派生类里重写GetMemoryUsage(),基类版本返回的永远是基类的大小。这是因为sizeof(*this)是编译期计算的,在基类的成员函数里,*this的静态类型就是基类,哪怕运行时实际指向的是派生类对象,也改变不了编译时确定的结果。

那怎么避免重复写return sizeof(*this)呢?这里有两个优雅的解决方案:

方案一:用CRTP(奇异递归模板模式)自动生成正确的实现

这是最省心的方式,通过模板让基类帮派生类自动搞定内存大小计算,完全不用手动重写函数。

核心思路是创建一个模板基类,让每个需要内存计算功能的类都继承它,并且把自身作为模板参数传进去。这样模板基类里的GetMemoryUsage()就能通过静态转换获取到派生类的大小:

#include <cstddef>

// CRTP基类,负责提供内存计算的虚函数实现
template <typename Derived>
struct MemoryTrackable {
    virtual ~MemoryTrackable() = default; // 必须加虚析构,不然多态删除会出问题

    virtual size_t GetMemoryUsage() const {
        // 把*this静态转换为派生类引用,确保sizeof拿到的是派生类的大小
        return sizeof(static_cast<const Derived&>(*this));
    }
};

// 基类A继承CRTP基类,传入自身作为模板参数
struct A : public MemoryTrackable<A> {
    int a;
};

// 派生类B同时继承A和CRTP基类(传入B自己)
struct B : public MemoryTrackable<B>, public A {
    int b;
};

// 更深层的派生类C同理
struct C : public MemoryTrackable<C>, public B {
    int c;
};

测试一下的话,用基类指针指向不同的派生类对象,调用GetMemoryUsage()都会返回对应对象的实际大小,完全不用在派生类里写任何重复代码。

方案二:用模板辅助函数简化重写

如果不想用CRTP,也可以在基类里写一个protected的模板辅助函数,让派生类重写时只需要一行代码调用它,避免重复写sizeof(*this):

#include <cstddef>

struct A {
    int a;
    virtual ~A() = default;
    virtual size_t GetMemoryUsage() const = 0;

protected:
    // 模板函数,帮派生类获取自身大小
    template <typename Derived>
    size_t GetDerivedSize() const {
        return sizeof(static_cast<const Derived&>(*this));
    }
};

struct B : public A {
    int b;
    size_t GetMemoryUsage() const override {
        return GetDerivedSize<B>(); // 只需这一行
    }
};

struct C : public B {
    int c;
    size_t GetMemoryUsage() const override {
        return GetDerivedSize<C>();
    }
};

这种方式虽然还是需要重写函数,但代码量极小,也避免了重复的逻辑。

为什么不能只靠基类方法实现?

简单来说,sizeof是编译期确定的,基类里的sizeof(*this)从编译那一刻起就固定为基类的大小,没办法在运行时动态“感知”到派生类的实际类型。必须通过多态让派生类自己提供大小信息,而CRTP就是把这个过程自动化的最佳实践。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:25:36