考虑接下来的两个课程:
struct Base
{
virtual ~Base()
{
}
virtual void foo() = 0;
};
struct Derived : public Base
{
virtual void foo()
{
}
};
以下是导致未定义的行为:
Base *obj = new Derived;
delete obj;
附加问题:如何将一个方法声明为虚拟,它在派生类中是虚拟的(即使虚拟关键字未在派生类中使用),但对于析构函数则不然?
答案 0 :(得分:4)
以下是导致未定义的行为:
不,这不是正确地调用未定义的行为 ,因为Base
的析构函数是virtual
。
从技术上讲,即使它没有被声明为虚拟,行为也会不未定义,这只是不受欢迎的。
没有。行为将是未定义的。
标准中的第5.3.5 / 3节说明,
在第一种选择中(删除 对象),如果是静态类型的 操作数与其动态不同 类型,静态类型应为基础 操作数的动态类型的类 而静态类型应该有一个 虚析构函数或行为 未定义。在第二个备选(删除数组)中的动态类型 要删除的对象与其静态类型不同,行为未定义。
我认为这有助于消除疑虑。: - )
答案 1 :(得分:2)
这不是未定义的行为。您已将基类析构函数声明为virtual
,因此在运行时,delete obj
将首先调用Derived
中的“默认”析构函数(因为您尚未明确声明一个),然后是Base
中的析构函数。
答案 2 :(得分:1)
对于任何类,构造函数和析构函数都不是继承的。这在标准中规定。因此,您的代码不会导致未定义的行为,因为它将调用该类的默认构造函数/析构函数。
正是由于这个原因,继承性不适用于析构函数/构造函数。从父对象继承构造函数/析构函数是没有意义的,因为此对象可能具有所有形式的不同成员。
答案 3 :(得分:1)
由于您已将基类的析构函数声明为虚拟,因此此处没有未定义的行为。
陈述:
Base *obj = new Derived;
delete obj;
将导致调用派生类的析构函数,然后调用Base类的析构函数。我没有得到第二个问题