Domanda

The question is based on following class hierarchy.

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

The output is :

Base1
Base1
Der1
Base2
Der3
v1 Base2
~Base2

And I get an exception.Why?(It only should generate memory leack)

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;}
};
È stato utile?

Soluzione

Why do you say you should only get a memory leak? It's undefined behavior; anything can happen.

The problem is probably because the virtual destructor also serves to determine the deallocation function and the address to pass to it. In your case, you end up passing the wrong address to ::operator delete. But that's just what is probably happening in practice. It's undefined behavior, and anything can happen.

Altri suggerimenti

If you plan to derive from a class and use a pointer to a base class to delete the object, you must declare it's destructor virtual. Otherwise, it is undefined behavior.

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top