C ++虚拟析构函数

时间:2013-11-27 17:32:07

标签: c++ virtual-destructor

问题基于以下类层次结构。

Base2* d3 = new Der3();
d3->v1();
delete d3;

输出结果为:

Base1
Base1
Der1
Base2
Der3
v1 Base2
~Base2

我得到一个例外。为什么?(它只会产生内存泄漏)

class Base1
{
public:
    Base1() {std::cout << "Base1" << std::endl; }
    ~Base1() {std::cout << "~Base1" << std::endl; }
    virtual void v1() { std::cout << "v1 Base1" << std::endl; }
    void v2() {std::cout << "v2 Base1" << std::endl;}
    void v3() {std::cout << "v3 Base1" << std::endl;}
};

class Base2
{
public:
    Base2() {std::cout << "Base2" << std::endl; }
    ~Base2() {std::cout << "~Base2" << std::endl; }
    void v1() { std::cout << "v1 Base2" << std::endl; }
    void v2() {std::cout << "v2 Base2" << std::endl;}
    void v3() {std::cout << "v3 Base2" << std::endl;}
};

class Der1 : public Base1
{
public:
    Der1() {std::cout << "Der1" << std::endl; }
    ~Der1() {std::cout << "~Der1" << std::endl; }
    virtual void v1() { std::cout << "v1 Der1" << std::endl; }
    virtual void v2() {std::cout << "v2 Der1" << std::endl;}
    void v3() {std::cout << "v3 Der1" << std::endl;}
};

class Der2 : public Base1,public Der1
{
public:
    Der2() {std::cout << "Der2" << std::endl; }
    ~Der2() {std::cout << "~Der2" << std::endl; }
    virtual void v1() { std::cout << "v1 Der2" << std::endl; }
    void v2() {std::cout << "v2 Der2" << std::endl;}
    void v3() {std::cout << "v3 Der2" << std::endl;}
};

class Der3 : public Base1,public Der1,public Base2
{
public:
    Der3() {std::cout << "Der3" << std::endl; }
    ~Der3() {std::cout << "~Der3" << std::endl; }
    virtual void v1() { std::cout << "v1 Der3" << std::endl; }
    void v2() {std::cout << "v2 Der3" << std::endl;}
    void v3() {std::cout << "v3 Der3" << std::endl;}
};

2 个答案:

答案 0 :(得分:5)

为什么你说你应该只是内存泄漏?这是未定义的行为;任何事情都可能发生。

问题可能是因为虚拟析构函数还用于确定释放函数和传递给它的地址。在您的情况下,您最终将错误的地址传递给::operator delete。但这正是实践中可能发生的事情。这是未定义的行为,任何事情都可能发生。

答案 1 :(得分:1)

如果计划从类派生并使用指向基类的指针来删除对象,则必须声明它是析构函数virtual。否则,它是未定义的行为。

class A
{
public:
    ~A() {}
...
};

class B : public A
{
public:
    ~B() {}
...
};

class C
{
public:
    virtual ~C() {}
...
};

class D : public C
{
public:
    virtual ~D() { }
...
};

B b; // OK, but bad practice
A* pa = new B; // not ok - when you try to delete
C* pc = new D; // ok