如何在父类虚函数中获取派生类对象的大小?
解决父类虚函数中获取派生类对象大小的问题
你遇到的核心问题是**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(); }
代码说明
- 虚函数
GetObjectSize:父类中定义的虚函数,在子类中重写。由于虚函数的调用是运行时绑定的,当父类函数调用GetObjectSize时,会根据实际对象的类型调用对应的子类实现。 - 子类中的
sizeof(*this):在CurrentAccount的GetObjectSize中,*this的静态类型是CurrentAccount,所以sizeof(*this)会正确返回子类对象的大小。 - 父类
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
相关产品推荐
相关产品推荐

