【发布时间】:2014-11-28 02:36:48
【问题描述】:
这是产生错误的程序:
#include <iostream>
#include <string>
using namespace std;
class Pet {
protected:
string name;
public:
Pet(string nam):name(nam){}
~Pet(){cout<< "Pet destroyed" << endl;} // attention
void play();
};
void Pet::play(){
std::cout<< "Pet " << name <<" is playing ..." <<endl;
}
class Cat : public Pet {
public:
Cat(string nam):Pet(nam){}
~Cat(){cout<< "Cat destroyed" <<endl;}
void play();
};
void Cat::play(){
cout<< "cat " << name <<" is playing ..." <<endl;
}
class Dog : public Pet {
public:
Dog(string nam):Pet(nam){}
~Dog(){cout<< "Dog destroyed" <<endl;}
virtual void play(); // attention
};
void Dog::play(){
cout<< "dog " << name <<" is playing ..." <<endl;
}
int main(void) {
Pet *cat1 = new Cat("Kitty");
Pet *dog1 = new Dog("Tom");
Pet *pet = new Pet("Nicky");
cat1->Pet::play();
dog1->play();
pet->play();
delete cat1;
delete pet;
delete dog1;
return 0;
}
这个程序编译得很好,但是当我运行它时,我得到了以下输出:
Pet Kitty is playing ...
Pet Tom is playing ...
Pet Nicky is playing ...
Pet destroyed
Pet destroyed
Pet destroyed
t(35634,0x7fff7ae04310) malloc: *** error for object 0x7f8623c03b68: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
错误信息之前的结果很有意义,但我不明白为什么会出现这个错误。错误在delete dog1; 行产生。 0x7f8623c03b68 是对象 dog1 的地址。由于dog1->play(); 执行得很好,所以应该很好地分配对象dog1 的内存空间。为什么错误提示“未分配指针被释放”???
当我将类 Pet 的析构函数更改为虚拟时,程序执行良好,没有错误。为什么???这是输出:
Pet Kitty is playing ...
Pet Tom is playing ...
Pet Nicky is playing ...
Cat destroyed
Pet destroyed
Pet destroyed
Dog destroyed
Pet destroyed
在这种情况下,删除 dog1 时,会先调用 Dog 的析构函数,然后调用 Pet 的析构函数。那么在这两种情况下,“虚拟”这个词对内存的变化有什么不同呢?
在这篇文章中 Why should I declare a virtual destructor for an abstract class in C++? 它解释了当基类的析构函数未声明为虚拟时,当删除引用子类对象的基类类型的指针时,将产生未定义的行为。那么这个错误只是所谓的未定义行为的一个例子吗?自从我从 Dog 类中删除虚拟后,程序运行良好。
我注意到这是否与上述文章中提到的问题相同。只是想确定并找到该错误的原因。
欢迎任何指示。谢谢。
【问题讨论】:
标签: c++ memory-management virtual