我有一个带有虚拟析构函数的基类method
。 A
具有使用默认析构函数的后代A
和B
。通过指向C
?
C
对象是否安全?
更具体地说,请考虑以下示例代码:
A
要运行的代码如下所示:
class A {
public:
A(){};
virtual ~A() {/* code here */};
};
class B: public A {
B() {/* code....*/};
/* NO DESTRUCTOR SPECIFIED */
};
class C: public B {/*same as above, no destructor */};
class D: public B {/* same as above, no destructor*/}
A* getAPointer(void); /* a function returning a C or a D*/
A* aptr=getAPointer();
/* aptr is declared as A*, but points to either an object of class C
or class D*/
delete aptr;
安全吗?它是否做得对:如果delete aptr
指向类aptr
的对象,C
首先调用aptr
的析构函数,然后C
析构函数,最后是B
的析构函数?
答案 0 :(得分:4)
通过指向A?
的指针删除C对象是否安全?
是的,它完全安全,因为B
,C
和D
类中的所有析构函数都将隐式虚拟。
自:
15.4析构函数[class.dtor]
10析构函数可以声明为虚拟(13.3)或纯虚拟(13.4); 如果在该类中创建了该类或任何派生类的任何对象 程序,应该定义析构函数。 如果某个类有基类 使用虚拟析构函数,它的析构函数(无论是用户还是 隐式声明的是虚拟的。
由于A
有一个虚拟析构函数,然后B
和C
,D
分别具有虚拟析构函数,并且:
delete aptr;
正常工作。
答案 1 :(得分:2)
是的,这很安全。将virtual
添加到派生类的析构函数中是多余的。
考虑该机制的工作原理。使用delete
时,运行时需要知道销毁链应该从哪个析构函数开始。如果delete
操作数的静态类型具有virtual
析构函数,那么运行时已经足以知道它必须承担额外的麻烦并检查动态类型。
在您的情况下,它会发现动态类型为C
,因此调用C::~C
。 C::~C
会自动转到B::~B
,而且会自动转到A::~A
。
要求C
(或B
' s)析构函数为virtual
是没有意义的。毕竟,如果C
为A::~A
,运行时必须找出动态virtual
类型。此时,它并不关心C::~C
是否virtual
。它会有什么不同?
答案 2 :(得分:0)
通过指向
listId
的指针删除C
的对象是否安全?
是。由于A
的析构函数是 virtual ,因此将调用A
的析构函数。这仅仅是由于动态调度的工作原理。