在继承中使用delete的意外行为,其中基指针对象指向最派生的类

Smi*_*ith 0 c++ polymorphism virtual class

在我的代码中,我使用了三个类.请参阅以下实施:

class Medicine 
{ 
   int a;
}

class Pain:public Medicine 
{
   int b;
}

class Comb:public Pain   
{
    string salt,com;
}
Run Code Online (Sandbox Code Playgroud)

所有类都只有参数化构造函数.而call()

call()
{
     cout<<"You are in class the_name_of_the_class"<<endl;
}
Run Code Online (Sandbox Code Playgroud)

我已经call()在所有这些中定义了一个具有相同名称的函数.(到现在为止,他们不被宣布为虚拟)

代码如下:

int main()
{       
    Pain *p[2];
    p[0]= new Comb("Salt","Com",2,110);
    p[1]= new Comb("SALT","COM",1,100);

    p[0]->call();

    delete p[0];
    delete p[1];
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:呼叫转到Pain的呼叫()

但是,如果我将Pain :: call()设为virtual(Medicine :: call()为real),则调用将转到Comb的call().没有任何问题!

但当我做Medicine *p[2]而不是Pain *p[2],发生以下错误

*** glibc detected *** ./a.out: free(): invalid pointer: 0x00000000022ed078 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3b64a760e6]
./a.out[0x400efe]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x3b64a1ecdd]
./a.out[0x400b79]
======= Memory map: ========
Run Code Online (Sandbox Code Playgroud)

更多的事情在这里,并以此结束

Abort(core dumped)
Run Code Online (Sandbox Code Playgroud)

为什么这样?当我使用virtual for Medicine :: call()时,这又消失了.(这个问题与Pain :: call()是否为虚拟无关).为什么会这样?

Luc*_*ore 8

您遇到了未定义的行为,因为基类的析构函数不是virtual.任何事情都可能发生.

如果通过指向基类的指针删除派生对象,则析构函数必须为virtual.这是一个规则.