我在一个名为virtual.cpp
:的文件中有这个简单的代码
#include <iostream>
class Parent
{
public:
virtual ~Parent(){ std::cout << "Parent Destructor" << std::endl; }
virtual void VirtualFunction()
{
std::cout << "VirtualFunctionInParent" << std::endl;
}
};
class Child: public Parent
{
public:
virtual ~Child() { std::cout << "Child Destructor" << std::endl; }
virtual void VirtualFunction()
{
std::cout << "VirtualFunctionInChild" << std::endl;
}
};
int main()
{
Child child1;
Parent *parent1 = &child1;
delete parent1;
}
它正确编译
g++ -Wall --pedantic -o virtual virtual.cpp
但当我运行它时,我得到了这个错误:
./virtual
Child Destructor
Parent Destructor
free(): invalid pointer
Annullato (core dump creato)
我认为这是因为我删除了指针parent1,所以这会擦除指针指向的内存,即&child1
。因此,当child1超出作用域时,Child析构函数会尝试释放已不存在的内存。
我的问题:
- 我的推理正确吗
- 如果我的推理是正确的,那就是处理这个问题的正确方法;超出范围";情况
我删除了指针parent1,因此这会擦除指针指向的内存。我的推理正确吗?
否。您正在从您的删除中获得一个核心转储。
只有从new
返回的地址可以被传递到delete
。
delete
不擦除存储器,因为存储器没有"擦除"的概念;擦除";状态
这是处理这个问题的正确方法"超出范围";情况
删除delete
行。没有必要。
在一个范围内创建的任何变量都会在该范围保留时自动进行管理。
new
分配的对象调用delete
。当这个对象超出范围时,它会被删除,所以没有什么特别的事情可以正确地销毁它。
当您希望对象在作用域内开始其生存期,并在作用域结束时结束其生存期时,不要使用new
和delete
。正常申报即可。
对要管理其生存期的对象使用new
和delete
。将它们分配给new
,并在完成后调用delete
。
首先,您不使用new
或任何其他方式来分配动态内存。因此,使用delete
是没有意义的。
要回答您的下一个问题,您必须首先告诉我们为什么要在孩子的地址上创建父指针?
更具体地回答您的问题
- 我的推理正确吗
您永远不会超出范围,因为您正在main((中向当前堆栈帧声明变量。为了向堆声明变量(超出范围(,必须使用动态内存分配。
Parent * parent1 = new(Child);
delete(parent1);
这段代码所做的是在堆中创建一个子类,然后在有效指向该子类的作用域的本地创建parent1指针。