我在玩一些c++的期货,并进入了一些确实引起我兴趣的事情。
class Base
{
public:
Base(){ cout<<"C: Base"<<endl;}
~Base(){ cout<<"D : Base"<<endl;}
};
class Derived: public Base
{
public:
Derived(){ cout<<"C: Derived"<<endl;}
~Derived(){ cout<<"D : Derived"<<endl;}
};
class Derived2: public Derived
{
public:
Derived2(){ cout<<"C: Derived2"<<endl;}
~Derived2(){ cout<<"D : Derived2"<<endl;}
};
class Derived3: public Derived2
{
public:
Derived3(){ cout<<"C: Derived3"<<endl;}
~Derived3(){ cout<<"D : Derived3"<<endl;}
};
void main()
{
Derived *Var = new Derived2();
delete (Derived3*)Var; //<---- this should cause some type of run-time error
}为什么上述操作不会产生错误。是因为Derived3中没有要发布的数据吗?还是我错过了什么?
但是相反,它会输出
C: Base
C: Derived
C: Derived2
D : Derived3 <--- SHOULD NOT BE POSSIBLE
D : Derived2
D : Derived
D : Base发布于 2011-04-01 08:31:48
C++语言没有任何广泛的“运行时错误”系统。一些语言特性可能会抛出异常或调用terminate(),这确实是“运行时错误”,但无效的delete不在这些特性中。
做一些像你所做的那样无效的事情会在C++中导致未定义的行为。未定义的行为意味着任何事情都可能发生,任何事情都是可能的。你的程序甚至可能在某种程度上表现得像是在“工作”。这就是你所观察到的。
尝试未定义的行为是一种毫无意义的练习。你观察到的结果完全没有意义,而且通常是不可重复的。
发布于 2011-04-01 08:37:10
对Derived3的强制转换是一个C风格的强制转换,它实际上与下面的C++风格的强制转换相同。
delete reinterpret_cast<Derived3*>(Var);这两种类型转换都告诉C++运行时,您希望强制运行时将类型转换(Var)所引用的内存解释为给定的类型(Derived3*),并完全理解其影响。因此,不会执行错误检查。
如果您担心强制转换的有效性,请使用以下方法:
static_cast<Derived3*>(Var):如果类型转换无效,则生成编译错误。dynamic_cast<Derived3*>(Var):如果强制转换无效,则返回0 (null)。
发布于 2011-04-01 08:32:15
它不会导致错误,因为您的析构函数不会更改或触及任何本地状态。
在典型的析构函数中,您将释放该实例分配的一些资源,这将导致您预期的问题。
话虽如此,它仍然不是好的代码,只是因为您显式地转换为错误的类型才会发生。在这种情况下,行为在技术上是未定义的,这意味着任何事情都可能发生,包括它现在正在做的“工作”。
https://stackoverflow.com/questions/5507969
复制相似问题