1
#include <iostream>

using namespace std;
int *p1;
struct base
{
    base():a(10){}
    int a;
    ~base()
    {
        cout << "~base()\n";
    }
};

struct derive:public base
{
    derive():b(5){

        p1=&b;
        cout << p1 << "\n";

    }
    int b;
    ~derive()
    {
        cout << "~derive()\n";
    }
};
int main()
{
    base *p = new derive;
    delete(p);
    cout << *p1;
    return 0;
}

I think b of derive shoule not be deleted,but what p1 pointed was deleted. how it works when I delete pointer of a base class that was pointed to an derive class when no dynamic inherit occured? sorry for my english.

Latyas
  • 35
  • 6
  • I think what you've hit there - i.e. declaring a pointer to a base class when constructing a derived object - will lead to undefined behaviour although I'm sure someone will correct me. – Component 10 Apr 19 '12 at 13:53
  • No, it's not undefined behavior. It's required to make inheritance and polymorphism work. – japreiss Apr 19 '12 at 14:03

3 Answers3

4

It's undefined behavior, because the base class destructor is not virtual. UB means anything can happen.

Don't delete a derived object through a base class if the base class doesn't have a virtual destructor.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
0

What one would expect with following code

base *p = new derive;
delete(p);

is that the derive object pointed to by p is cleaned up correctly. This can only be done when the base class has a virtual destructor. This is not the case here, so whatever cleanup that happens in the derive destructor will not happen, which is an unhealthy situation (or as put more technically by Luchian: undefined behavior).

stefaanv
  • 14,072
  • 2
  • 31
  • 53
-1

I am not 100% I understand the question, and it has been awhile since ive used c++, but I will give it a shot.

Generally if you have an object that is going to be allocated dynamically you need to have 3 things, that my teachers used to call "The trilogy of evil".

  1. Copy Constructor
  2. Assignment Operator
  3. Virtual Destructor

the first two have to do with making "deep copies" while the third is what we are concerned with.

You need to mark your destructor virtual to add it to the objects virtual table, that way the destructors will call up a chain.

so:

class A
{
    public A(A & copy) { ... }
    public static A & operator = (A & rhs) { ... }
    virtual ~A() { ... }
}

class B : A { } // inherits A's destructor via virtual table
Tom Fobear
  • 6,729
  • 7
  • 42
  • 74
  • "Generally if you have an object that is going to be allocated dynamically you need to have 3 things" this is wrong. – Luchian Grigore Apr 19 '12 at 13:58
  • I agree with Luchian. A more accurate statement is, "Generally if you have an object that *handles a resource*, you need to have 3 things." Dynamic memory is a common resource that is cited, but sockets and file handles are good examples as well – riwalk Apr 19 '12 at 14:04
  • It is not wrong, it is good practice. Plus I said "Generally". – Tom Fobear Apr 19 '12 at 14:10
  • 1
    It **is** wrong. In fact, it's good practice to leave the implementation [of destructor, copy constructor and assignment operator] of types that don't manage resources up to the compiler. – Luchian Grigore Apr 19 '12 at 14:24