在继承中使用delete的意外行为,基指针对象指向派生程度最高的类
Unexpected behaviour using delete in inheritence, with base pointer objects pointing to the most derived class
在我的代码中,我使用了三个类。参见以下实现:
class Medicine
{
int a;
}
class Pain:public Medicine
{
int b;
}
class Comb:public Pain
{
string salt,com;
}
所有类都只有参数化的构造函数。call()
就像
call()
{
cout<<"You are in class the_name_of_the_class"<<endl;
}
我在所有这些函数中定义了一个同名的函数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;
}
输出:呼叫转到Pain的呼叫()
然而,如果我将Pain::call()设为虚拟的(Medicine::call(是真实的),那么调用将转到Comb的call()。没问题!
但是当我做CCD_ 3而不是CCD_,出现以下错误
*** 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: ========
更多的事情发生在这里,这以结束
Abort(core dumped)
为什么会这样?当我将virtual用于Medicine::call()时,这种情况再次消失。(这个问题与Pain::call()是否为虚拟无关)。为什么会发生这种情况?
由于基类的析构函数不是virtual
,因此您遇到了未定义的行为。任何事情都有可能发生。
如果通过指向基类的指针删除派生对象,则析构函数必须是virtual
。这是一条规则。
根据Scott Mayers的"Effective C++",如果要在程序中定义派生类,则应在基类中将析构函数定义为虚拟的,否则程序在运行时会有不同的行为(可能是内存泄漏、错误输出、崩溃)。
当我们可以通过指向基类的指针删除派生类的实例时,虚拟析构函数很有用:
class Base
{
// some code
};
class Derived : public Base
{
~Derived()
{
// some code
}
}
在这里,我没有声明Base的析构函数是虚拟的。现在,让我们来看看以下代码:
Base *b = new Derived();
// use b
delete b; // Here's the problem!
由于Base的析构函数不是虚拟的,并且b是指向派生对象的Base*,因此删除b具有未定义的行为。在我的实现中,对析构函数的调用也将像任何非虚拟代码一样被解析,这意味着基类的析构函数将被调用,而不是派生类的析构因子,从而导致资源泄漏。此外,在使用继承时,将析构函数声明为虚拟的总是安全的,无论它是否有用。
- 对象指针在c++中是如何工作的
- C++ 对象指针数组的复制构造函数
- 在对象指针上调用 Delete 是否会递归删除其动态分配的成员
- 什么更好?返回对象指针列表?或返回指向对象列表的指针?
- 正确初始化和销毁对象指针的C++数组?
- 如何深度复制链表对象指针
- 对象指针 c++ 的全局向量错误
- 如何将 c++ 类包装到 python 中,以便我可以使用 pybind11 访问其成员的公共方法(成员是一个对象指针)
- 静态对象指针
- 正在将对象指针数组初始化为NULL
- 如何使用条件表达式返回对象指针?
- std::flush可以用于将对象指针转换为其封闭数组指针吗
- 使用C对象指针构建PyObject*
- 如何在使用对象指针时访问成员函数
- 静态强制转换允许转换对象指针,但不允许转换整数
- C++ abort() 在函数内的抽象类对象指针调用上
- 指向函数的对象指针
- 访问指向对象指针向量的指针的第一个元素?
- 如何将对象/指针正确存储到 Qlist 中
- 对象指针打印结果以相反的顺序进行