Я создал подкласс класса B для класса, который я назову A.
Я написал этот код для работы, поэтому я собираюсь обобщить фактический код:
class A
{
public:
A ()
{
important_variable = new Type();
...
};
~A (void) { delete(important_variable); }; // Default destructor
// more methods
protected:
Type *important_variable;
};
class B : public A
{
public:
B() : A() { important_variable = another_var; }
~B() {};
Type *another_var;
};
Наличие этого кода для B вызвало сбой моей программы с помощью "Необработанного исключения".
Теперь, когда я меняю код для класса B на это:
class B : public A
{
public:
B() : A() { another_var = new Type(); important_variable = another_var; }
~B() {};
Type *another_var;
};
Исключение уходит.
Я думаю, что мой исходный код для B вызвал мою программу, потому что A пытался удалить переменную, на которую все еще указала другая переменная. Правильно ли это рассуждение? Почему новый код для B заставляет мою программу работать?
В вашем коде есть много недостатков, но наиболее вероятным причиной сбоя является эта строка:
important_variable = another_var;
another_var
не указывает нигде, что можно удалить. Но important_variable
указывается на одно и то же место, а затем удаляется в конструкторе A
Ваше "решение" маскирует проблему за счет утечки памяти. Когда вы это сделаете
another_var = new Type(); important_variable = another_var;
исходный динамически выделенный объект Type
который указывает important_variable
, потерян.
Кроме того, вам нужно следовать правилу из трех.
new и delete предназначены только для распределения кучи. Я подозреваю, что в вашем первом списке класса B в стеке скорее всего выделяется another_var
и именно это вызывает исключение в деструкторе. Кроме того, всякий раз, когда у вас есть базовый класс, вы действительно должны сделать его деструктор virtual
.
Исходная версия разбилась, потому что вы установили important_variable
в uninitialised another_var
а затем попытались удалить это неинициализированное значение. В "исправленной" версии вы, по крайней мере, не удаляете неинициализированные переменные, но все же в ней содержится утечка памяти - вы назначаете новую выделенную память important_variable
а затем сразу же присваиваете этой переменной значение another_var
, поэтому первоначально выделенная память больше не доступный и протекающий.