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

如何在父类虚函数中获取派生类对象的大小?

解决父类虚函数中获取派生类对象大小的问题

你遇到的核心问题是**sizeof是编译时运算符**——在父类Account的PrintBalance函数中,*this的静态类型是Account,所以sizeof(*this)在编译阶段就被固定为Account类的大小,完全不考虑运行时实际指向的派生类对象。要实现动态获取对象的实际大小,我们需要借助C++的运行时多态特性。

解决方案:添加虚函数返回对象大小

我们可以在父类中定义一个虚函数,专门用来返回当前对象的实际大小,然后在子类中重写这个函数(利用子类中*this的静态类型是子类本身的特性)。这样即使在父类函数中调用该虚函数,也会自动绑定到子类的实现,得到正确的派生类对象大小。

修改后的完整代码如下:

#include <iostream>
using namespace std;

class Account {
protected:
    int var1;
    int var2;
    double m_balance;
public:
    Account(double d) : m_balance(d) {}
    virtual double GetBalance() { return m_balance; }
    
    // 新增虚函数:返回当前对象的实际大小
    virtual size_t GetObjectSize() const {
        return sizeof(*this);
    }
    
    virtual void PrintBalance() { 
        // 调用虚函数获取实际大小,而非直接用sizeof(*this)
        cout << "size in Parent= " << GetObjectSize() << endl; 
    }
};

class CurrentAccount : public Account {
    int var3;
    int var4;
public:
    CurrentAccount(double d) : Account(d) {}
    
    // 重写虚函数,返回子类对象的大小
    size_t GetObjectSize() const override {
        return sizeof(*this);
    }
    
    void PrintBalance() override {
        Account::PrintBalance(); // 父类函数会调用子类的GetObjectSize
        cout << "size in Derived = " << sizeof(*this) << endl;
        cout << "Current account balance: " << GetBalance() << endl;
    }
};

int main() {
    CurrentAccount cAcc(1000);
    CurrentAccount *pCurrent = &cAcc ;
    pCurrent->PrintBalance();
    pCurrent->GetBalance();
}

代码说明

  1. 虚函数GetObjectSize:父类中定义的虚函数,在子类中重写。由于虚函数的调用是运行时绑定的,当父类函数调用GetObjectSize时,会根据实际对象的类型调用对应的子类实现。
  2. 子类中的sizeof(*this):在CurrentAccount的GetObjectSize中,*this的静态类型是CurrentAccount,所以sizeof(*this)会正确返回子类对象的大小。
  3. 父类PrintBalance的行为:当子类调用Account::PrintBalance()时,父类函数中的GetObjectSize()会调用子类的重写版本,因此输出的是派生类对象的大小,而不是父类的大小。

可选优化:用CRTP自动实现(避免手动重写)

如果你有多个派生类,不想每个都手动重写GetObjectSize,可以使用**奇异递归模板模式(CRTP)**来自动生成该函数:

#include <iostream>
using namespace std;

template<typename Derived>
class AccountBase {
protected:
    int var1;
    int var2;
    double m_balance;
public:
    AccountBase(double d) : m_balance(d) {}
    virtual double GetBalance() { return m_balance; }
    
    size_t GetObjectSize() const {
        // 强制转换为派生类类型,获取正确大小
        return sizeof(static_cast<const Derived&>(*this));
    }
    
    virtual void PrintBalance() { 
        cout << "size in Parent= " << GetObjectSize() << endl; 
    }
};

// 父类继承自模板基类
class Account : public AccountBase<Account> {
public:
    Account(double d) : AccountBase<Account>(d) {}
};

// 子类继承自模板基类
class CurrentAccount : public AccountBase<CurrentAccount> {
    int var3;
    int var4;
public:
    CurrentAccount(double d) : AccountBase<CurrentAccount>(d) {}
    
    void PrintBalance() override {
        AccountBase<CurrentAccount>::PrintBalance();
        cout << "size in Derived = " << sizeof(*this) << endl;
        cout << "Current account balance: " << GetBalance() << endl;
    }
};

这种方式通过模板在编译时确定对象类型,无需手动重写GetObjectSize,适合派生类较多的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:14:05