-2

I want to know why ~Test2 and ~Test1 are not called in this case:

public class Test1
{
public:
    Test1() { Console::WriteLine("Test1\n"); }
    virtual ~Test1() { Console::WriteLine("~Test1\n"); }
};

class Test2 : public Test1
{
public:
    Test2()  { Console::WriteLine("Test2\n"); }
    virtual ~Test2() { Console::WriteLine("~Test2\n"); }
};

int main(array<System::String ^> ^args)
{
    Console::WriteLine(L"Testing destructors");

    //Test1* t1 = new Test2(); // Test2 is cast as Test1
    //delete t1;

    //Console::ReadKey();
    //Console::WriteLine(L"Now void*:");

    void*  v = new Test2(); 
    delete v;

    Console::ReadKey();

    return 0;
}

Is this a
- A rule that requires all compilers act this way?
- A bug in C++ compiler implementation?
- A behavior left undefined and so it varies from compiler to compiler?

ILIA BROUDNO
  • 1,539
  • 17
  • 24

3 Answers3

1

What you need is a virtual destructor in the base class. This will get you the expected behavior. Otherwise, the behavior is undefined.

virtual ~Test1() { Console::WriteLine("~Test1\n"); }

More Details here:

SBS
  • 806
  • 5
  • 13
  • Yes you are right. Virtual is what is missing. That was a silly question in retrospect. Now uncomment those 2 other lines: //void* v = new Test1(); //delete v; No destructor is now called as a result of delete v; Why is that? P.S. Sorry but I edited the question and now the answer no longer fits. You did answer the previous version. – ILIA BROUDNO Aug 08 '17 at 17:36
0

It does not call the destructor because the pointer you are calling delete on is not a pointer to your object type. How is delete supposed to know that a void* is pointing to a particular type? It can't. So it simply deletes the memory since void has no destructor.

Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175
  • How does delete know? Well how does it know the type when I downcast it from Test2 to Test1 as in the commented out code and then delete it? – ILIA BROUDNO Aug 10 '17 at 17:14
0

t1 is a void, it is not of type Test1, the compiler has no way of knowing that you want to delete a Test1. You can try casting it back:

delete static_cast<Test1*>(t1);
zdan
  • 28,667
  • 7
  • 60
  • 71
  • Compiler may not know but between compiler and run-time it is knowable if that's a word. For example in this code: Test1* t1 = new Test2(); delete t1; it still knows to call ~Test2. Also a workaround is not what I am looking for. – ILIA BROUDNO Aug 10 '17 at 17:25