在对象的析构函数中不应使用其动态类型
8.16 ID_virtualCallInDestructor
对象的“动态类型(dynamic type)”在其析构过程中不生效。
执行基类析构函数时,属于派生类的成员已被析构,基类析构函数不能使用派生类动态类型。
对于正在析构的对象,不应:
- 调用派生类重写的虚函数
- 通过 typeid 判断对象的动态类型
- 通过 dynamic_cast 转换对象的动态类型
注意,如果在析构函数中调用未实现的纯虚函数会导致标准未定义的行为。
示例:
class A {
virtual void clear() {}
public:
~A() { clear(); } // Non-compliant
};
class B: public A {
int* p = new int[8];
void clear() override { delete[] p; } // Invalid
};
虽然派生类 B 重写了 clear 函数,但在基类 A 的析构函数中不生效,相关内存没有被正确释放。
应将基类的析构函数设为虚函数,在派生类的析构函数中释放资源:
class A {
public:
virtual ~A() = default;
};
class B: public A {
int* p = new int[8];
public:
~B() override { delete[] p; } // Compliant
};
相关
依据
ISO/IEC 14882:2003 10.4(6)-undefined
ISO/IEC 14882:2011 10.4(6)-undefined
参考
C++ Core Guidelines C.82
MISRA C++ 2008 12-1-1
Effective C++ item 9