非虚拟父类析构函数

时间:2013-02-06 14:21:56

标签: c++

class Person
{
public:
    Person(std::string& name,long id) : name_(name), id_(id) {}
    ~Person() {}
private:
    std::string& name_;
    long id_;
};

class Student : public Person
{
public:
    Student(std::string& name, long id) : Person(name,id) {}
    Student(std::string& name, long id, const std::vector<int*>& courses) : Person(name,id), courses_(courses) {}
    virtual ~Student() {
        std::vector<int*>::iterator it;
        for (it = courses_.begin(); it != courses_.end(); ++it)
        delete (*it);
    }
    const std::vector<int*>& getCourses() const { return courses_; }
private:
    std::vector<int*> courses_;
};

int main(){
    std::string name("Rina");
    std::vector<int*> courses;
    courses.push_back(new int(1345));
    Person* p = new Student(name,37,courses);
    Student* s = (Student*)p;
    std::cout << (*(s->getCourses().at(0)));
    delete p;
}

我明白了

delete p;

让我们意识到

的问题
~Person()

不是虚拟的。 我的问题是:为什么要

~Person() 

虚拟?

2 个答案:

答案 0 :(得分:2)

出于同样的原因,您将其他方法设为虚拟。

Person *p;
...

delete p;
如果析构函数不是虚拟的,那么

不会正确处理Person的子类。即它只会调用Person组件而不是子类组件(例如Employee

答案 1 :(得分:1)

因为这就是标准所说的。 delete p;是未定义的行为。

5.3.5删除[expr.delete]

  

3)在第一个备选(删除对象)中,如果要删除的对象的静态类型与其不同   动态类型,静态类型应该是要删除的对象的动态类型的基类   static类型应具有虚拟析构函数或行为未定义。在第二种选择中(删除   array)如果要删除的对象的动态类型与其静态类型不同,则行为未定义。

它之所以可能是因为它能够处理调用派生类析构函数(比如调用虚函数)而不会增加不需要它的类的开销(即不要通过引入一个类来使所有类具有多态性) virtual析构函数默认只处理这种特殊情况。)