   [.net] C++/CLI destructors always virtual?
  Are destructors and finalizers always virtual in C++/CLI?  I wrote the following code that suggests they are:using namespace System;ref class Base{public:Base(){Console::WriteLine(L"Base::Base()");}~Base(){Console::WriteLine(L"Base::~Base()");}!Base(){Console::WriteLine(L"Base::!Base()");}};ref class Derived : Base{public:Derived(){Console::WriteLine(L"Derived::Derived()");}~Derived(){Console::WriteLine(L"Derived::~Derived()");}!Derived(){Console::WriteLine(L"Derived::!Derived()");}};int main(array<System::String ^> ^args){    Base^ base = gcnew Derived;GC::Collect();    return 0;}Output:Base::Base()Derived::Derived()Derived::!Derived()Base::!Base()Press any key to continue . . .Same thing for destructor, even though no virtual keyword.   
  AFAIK c++ destructors are always virtual... it should be the same for c++/CLI I suppose...   ;  cignox1: No. C++ destructors are not virtual by default. It is, however, legal to omit the virtual keyword in a derived class as long as the base function is marked virtual.18:50 < Zao> geordi: struct A { tracked::B x; }; struct B : A { tracked::B y; }; int main() { A* p = new B; delete p; }18:50 < geordi>  B0*  B1*  B0~  || leaked: B1C++ FAQ Lite - [20.7] When should my destructor be virtual?;Quote:Original post by cignox1AFAIK c++ destructors are always virtual...This is incorrect.   ;  ref types in C++/CLI always inherit from System::Object, even if you don't explicitly specify it, which has a virtual destructor.   ;  Sorry guys, I don't know why but I wrote the exact opposite of what I meant... I suppose that I should read what I write twice before posting it :-)EDIT: now that I think of it, it could be also due to the fact that I mostly use java and C# these days... sorry to the OP: I should be more careful when I answer...   ;  SiCrane reflector doesn't reveal a virtual destructor on System::Object? But i'll take your word for it :PI did my own test which supports that statement:// Test.cpp : main project file.#include "stdafx.h"using namespace System;ref class Base{public:Base(){Console::WriteLine(L"Base::Base()");}~Base(){Console::WriteLine(L"Base::~Base()");}protected:!Base(){Console::WriteLine(L"Base::!Base()");}};ref class Derived : Base{public:Derived(){Console::WriteLine(L"Derived::Derived()");}~Derived(){Console::WriteLine(L"Derived::~Derived()");}protected:!Derived(){Console::WriteLine(L"Derived::!Derived()");}};int main(array<System::String ^> ^args){    Derived^ derived = gcnew Derived;delete derived; //calls the destructor (which also calls the base classes destructor)GC::Collect(); //without the destructor call above, this would call the finalizers. It doesn't seem to do anything if the object was "deleted".    return 0;}//the result of the code above (with both variations of Main)//Base::Base()//Derived::Derived()//Derived::~Derived()//Base::~Base()//Press any key to continue . . .//if "delete derived;" is commented out you get this//Base::Base()//Derived::Derived()//Derived::!Derived()//Base::!Base()//Press any key to continue . . .//it didn't make a difference if the destructor of the base class was virtual, and (although "they" say to make the finalizer protected), not putting the finalizer in the protected: area didn't affect the behavior (of this example)//-----------------------------------------------------------------------------------------------//this version will call the finalizers, which happens automatically when objects go out of scope//int main(array<System::String ^> ^args)//{//    {//  Derived^ derived = gcnew Derived;//    }    //    //    return 0;//}//Base::Base()//Derived::Derived()//Derived::!Derived()//Base::!Base()//Press any key to continue . . .//ALSOint main(array<System::String ^> ^args){    Derived^ derived = gcnew Derived;delete derived;    delete derived;    return 0;}//so it's ok to call delete repeatedly, so this explains why people check a bool value to test if the class was already disposed!Base::Base()Derived::Derived()Derived::~Derived()Base::~Base()Derived::~Derived()Base::~Base()Press any key to continue . . .;  First off:Managed objects do not have destructor. They do have finalizers though, but those are an entirely different beast. A finalizer is called sometime after the object's last reference has been released, and is used primarily to ensure that any unmanaged resources are released. It cannot, and should not, access any managed reference types that it previously may have held references to, as they may no longer be valid.C++/CLI "destructors" on managed types are actually just an implementation of the IDisposable interface, that is:ref class Q {public:    ~Q() {}};becomes (approximately, the actual implementation is a bit different than this, as ~Q stays a member function, and dispose invokes it)ref class Q : IDisposable {public:    virtual void Dispose() {}};C++/CLI supports psuedo stack allocation of managed types by simply declaring them as you would any other variable, however at the end of the scope their memory is not released, but their dispose method is executed (if it exists).{    Q q;    //do something with q}   //q.Dispose();C++/CLI also allows you to "delete" managed references, which will call the "destructor", aka Dispose:{    Q^ q = gcnew Q();    try {   //use Q    } finally {   delete q;    }}I should note that the actual implementation of all of these things is a bit more complex than what I've explained. C++/CLI is not a language you should use for general purpose .net development, despite being a first class .Net language. If you're looking to do managed development, stick with C# or Vb.Net, if you're attempting to wrap up unmanaged code in a C++/CLI layer, then the following rule is probably the best one to use: KISS.   