当我使用 Visual Studio 2010 运行以下 C++ 代码时,如果任何派生类函数被声明为虚函数,程序就会卡在变量删除处。谁能解释一下?
void testInheritance()
{
class a
{
public :
char x;
void fn1()
{
std::cout<<"\n In Class A Function 1 : "<<x;
}
virtual void fn2()
{
std::cout<<"\n In Class A Function 2 : "<<x;
}
a()
{
x='A';
std::cout<<"\n In A() : "<<x;
}
~a()
{
std::cout<<"\n In ~A : "<<x;
}
};
class b: public a
{
public :
char y;
virtual void fn1()
{
std::cout<<"\n In Class B Function 1 : "<<y;
}
void fn3()
{
std::cout<<"\n In Class B Function 3 : "<<y;
}
b()
{
y='B';
std::cout<<"\n In B() : "<<y;
}
~b()
{
std::cout<<"\n In ~B : "<<y;
}
};
a* var = new b();
delete var;
}
更多信息:
我知道要调用 b::fn1 和类 b 的析构函数,我需要在基类(即类 a)中将它们声明为虚拟的。但是,如果我不这样做,甚至不将 b 类(也不是 a 类)中的任何函数声明为虚拟函数,它应该同时调用 fn1 和 a 的析构函数,这会完美地发生。但是,当我声明 b 的任何成员(但不是 a)是虚拟的,无论是新成员还是重载成员,然后它在用 VS2010 编译时挂起,在 linux 上用 gcc4.4.4 编译时中断。它应该调用其中一个析构函数并正常工作,但我无法理解程序中断的原因。
此外,在 Visual Studio 2010 中使用 Intellitrace 时,我尝试在它挂起的地方中断代码,我收到以下消息:
该进程似乎已死锁(或未运行任何用户模式代码)。所有线程都已停止。
最佳答案
您期望意外行为,因为您在您的程序中创建了一个未定义的行为。
使用指向具有非虚析构函数
的基
类的指针删除派生
类对象会导致未定义的行为
。未定义的 Beahavor 意味着任何事情都可能发生。
C++ 标准第 1.3.24 节指出:
允许的未定义行为的范围包括从完全忽略具有不可预测结果的情况,到在翻译或程序执行期间以环境特征的文档化方式表现(有或没有发布诊断消息),到终止翻译或执行(发布诊断消息)。
如何解决问题?
基类中的析构函数应该是虚拟的。
关于c++ - 虚函数的意外行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6659691/