C++派生类转基类内存问题:如何正确释放指针并获取派生类属性
问题解决
现有代码隐患
Base类未定义虚析构函数,直接通过基类指针释放派生类对象会导致派生类析构函数不执行,触发未定义行为GetValue、GetDerivedValue函数声明有int返回值,但实际没有return语句,存在语法隐患- 公有派生场景下
pbase = (Base *) d;的C风格强制转换是多余操作,派生类指针可以隐式转换为基类指针
修复方案
第一步:修复类和函数定义
class Base { public: Base () { abc = 0; } // 新增虚析构函数,保证多态析构正确性 virtual ~Base () { abc = 0; } int abc; }; class Derived : public Base { public: Derived () { def = 0; } ~Derived () { def = 0 ; } int def; }; // 修改返回值为void,避免无return的问题 void GetDerivedValue (int &def) { def = 5; } void GetValue (Base *&pbase) { Derived *d = new Derived (); GetDerivedValue (d->def); pbase = d; }
第二步:main函数中读取属性+释放内存
int main () { Base *pbase = NULL; GetValue (pbase); int def_value = 0; // 类型转换获取派生类指针,dynamic_cast会做运行时类型检查 Derived* pderived = dynamic_cast<Derived*>(pbase); if (pderived != nullptr) { def_value = pderived->def; // 此时def_value的值为5 } // 所有属性读取完成后,直接释放基类指针即可 // 因为Base有虚析构函数,会依次调用Derived、Base的析构函数,不会出现内存泄漏或错误 delete pbase; pbase = nullptr; return 0; }
内存释放规则说明
- 释放时机必须在所有对该对象的成员操作完成之后,上述示例中读取完
def值后释放是最优选择 - 如果你能100%确认
GetValue返回的基类指针一定指向Derived对象,也可以用static_cast<Derived*>(pbase)做转换,性能更高但没有运行时安全检查 - 如果不方便修改
Base类添加虚析构函数,也可以在转换得到Derived*指针后,释放pderived指针,同样能保证析构完整
内容的提问来源于stack exchange,提问作者Aditya Ram Mangalampalli
相关产品推荐
相关产品推荐

