У меня есть виртуальный деструктор и массив в моем базовом классе. Как я могу заставить это работать? - PullRequest
1 голос
/ 30 января 2012

Пример:

class base
{
public:
  base()
  {
    // allocate memory for basearray
  }
  virtual ~base()
  {
    // delete basearray
  }

protected:
  float* basearray;
};

class derived1 : public base
{
public:
  derived1()
  {
    // allocate memory for derivedarray
  }
  ~derived1()
  {
    // delete derived array
  }

protect:
  float* derivedarray;
};

void main()
{
  derived1 d;

  ...

  base* pb = &d;

  ...

  // Delete base array? 
}

У меня есть виртуальный деструктор и массив в моем базовом классе.Если деструктор базового класса будет переопределен деструктором производного класса, то базовый массив не будет удален.Какое хорошее решение?

Ответы [ 5 ]

9 голосов
/ 30 января 2012

Деструктор базового класса автоматически вызывается сразу после запуска деструктора производного класса.

2 голосов
/ 30 января 2012

Когда деструктор производного объекта и деструктор базы виртуальный, будут вызваны оба деструктора.Вы можете подтвердить это здесь: http://ideone.com/RZamr

Порядок будет противоположен порядку конструкторов, т. Е. При создании сначала будет вызван конструктор base, а затем - derived.При разрушении сначала будет вызван деструктор derived, затем деструктор base.

1 голос
/ 30 января 2012

Виртуальные деструкторы не работают так же, как другие виртуальные функции, поскольку виртуальный деструктор базового класса никогда не переопределяется.Вместо этого, когда подкласс предоставляет свой собственный деструктор, этот деструктор подкласса срабатывает, тогда деструктор базового класса также срабатывает.«Виртуальный» здесь используется для того, чтобы при удалении объекта производного класса через указатель базового класса C ++ знал, что вызывать деструктор на основе динамического типа объекта (подкласса), а не статического типа указателя (суперкласс).В результате вам не нужно делать ничего особенного здесь.Деструктор базового класса будет работать как обычно.

Надеюсь, это поможет!

0 голосов
/ 31 января 2012

Здесь нет проблем. Деструктор базового класса вызывается сразу после вызова деструктора производного класса.

Есть только одно обстоятельство, когда это не так: удаление вызывается по указателю на базовый класс, где деструктор базового класса равен , а не виртуальный.

Во всех случаях, когда у вас есть локальный экземпляр класса, созданный в стеке, и функция или метод завершаются, даже из-за исключения, экземпляр корректно уничтожается.

При любых обстоятельствах, когда экземпляр класса равен new d и впоследствии удаляется с помощью указателя на конкретный класс, который был создан, экземпляр корректно уничтожается.

Когда экземпляр класса new d, но удален через указатель базового класса, экземпляр корректно уничтожается только тогда, когда базовый класс имеет виртуальный деструктор (либо сам объявленный virtual, либо его собственная база имеет виртуальный деструктор), экземпляр правильно уничтожен.

0 голосов
/ 30 января 2012

При переопределении деструктора деструктор базового класса по-прежнему вызывается, пока он определен как «виртуальный», что вы и сделали.

Так в этом примере:

  class base
  {
  public:
     base()
     {
        myarray = new float[100];
     }

     ~base()
     {
        delete[] myarray;
     }

  private:
     float* myarray;
  }


  class derived : public base
  {
  public:
     derived()
     {
     }

     ~derived()
     {
     }
  }

Это не удалит «myarray» и приведет к утечке памяти, потому что деструктор базового класса скрыт деструктором производного класса.Однако:

  class base
  {
  public:
     base()
     {
        myarray = new float[100];
     }

     virtual ~base()
     {
        delete[] myarray;
     }

  private:
     float* myarray;
  }


  class derived : public base
  {
  public:
     derived()
     {
     }

     ~derived()
     {
     }
  }

Это удалит массив.

Имейте в виду, что конструкторы вызываются из базового класса вверх, поэтому сначала вызывается конструктор базового класса, а затем производный класстогда как деструкторы вызываются в обратном порядке, поэтому деструктор вашего производного класса вызывается раньше, чем деструктор базового класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...