Деструкторы и наследование в C++?
Я использую Borland C++ Builder.
И у меня была проблема
#include <Classes.hpp>
class TMyObject : public TObject
{
__fastcall TMyObject();
__fastcall ~TMyObject();//I would like to inherite my destructor from TObject
};
__fastcall TMyObject::TMyObject() : TObject()//it will inherited my constructor from TObject
{
}
И для этого нового деструктора, который унаследует ~TObject
?
__fastcall TMyObject::~TMyObject?????????????
4 ответа
Это может быть решено в TObject
уровень. Его деструктор должен быть виртуальным:
#include <Classes.hpp>
class TObject
{
__fastcall TObject();
virtual __fastcall ~TObject();
};
Таким образом, вы можете сделать:
TObject * pobj = new TMyObject();
delete pobj;
или же
TMyObject * pobj = new TMyObject();
delete pobj;
Оба деструктора будут называться (~TMyObject()
сначала, а потом ~TObject()
) и у вас не будет утечки.
Деструктор базового класса будет автоматически вызываться компилятором, когда закончится время жизни вашего объекта. вам не нужно называть это явно.
TMyObject::TMyObject() : TObject()
Не наследует конструктор.
Он называется списком инициализатора члена и инициализирует объект базового класса определенным значением.
Когда вы создаете объект.
TMyObject obj;
Конструкторы будут вызываться по порядку:
constructor of TObject
constructor of TMyObject
По истечении времени жизни объекта деструкторы будут вызываться в следующем порядке:
destructor of TMyObject
destructr of TObject
Компилятор сделает это за вас, не нужно вызывать его явно.
Если вы уничтожите TMyObject
через ссылку типа TMyObject
тебе не нужно ничего делать. Если у вас есть указатель / ссылка типа TObject
к TMyObject
все пойдет не так. Только TObject
будет называться деструктор, а не TMyObject
один:
TObject* p = new TMyObject;
delete p; // Only the TObject::~TObject is called, not TMyObject::~TMyObject.
Чтобы решить, какой деструктор вызывать, отложить до времени выполнения, вам нужно указать деструктор как virtual
в TObject
, Всякий раз, когда у вас есть класс, от которого предполагается получить наследник, деструктор должен быть виртуальным. В противном случае всегда существует риск утечки ресурсов, когда деструктор производного класса не вызывается должным образом.
Что приводит вас в замешательство, так это то, что вы можете указать "какой" конструктор базового класса, который вы хотите использовать, как в следующем примере. Но вы не можете / не должны указывать деструктор.
TMyObject::TMyObject() : TObject()
Вы можете использовать другой конструктор, скажем, TObject (int i)
написав
TMyObject::TMyObject() : TObject (3)
Объект может быть уничтожен только одним способом, но он может быть построен несколькими способами (с помощью разных конструкторов).
Короче говоря, вам не нужно упоминать имя деструктора базового класса в деструкторе производного класса. Как только вы уничтожите производный объект (скажем, делая delete derivedObj
), он сначала вызовет деструктор производного класса, а затем сам деструктор базового класса.