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.

2
  • 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. Commented Apr 19, 2012 at 13:53
  • No, it's not undefined behavior. It's required to make inheritance and polymorphism work. Commented Apr 19, 2012 at 14:03

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

@Latyas undefined behavior means anything can happen, including the deletion of what p1 pointed to.
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).

Comments

-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

4 Comments

"Generally if you have an object that is going to be allocated dynamically you need to have 3 things" this is wrong.
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
It is not wrong, it is good practice. Plus I said "Generally".
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.