Я не могу понять это поведение. У меня есть класс А,
class A
{
public:
int ch;
char *s;
A()
{}
A(char *st):ch(0)
{
s = new char[10];
strcpy(s,st);
}
A(const A& rhs):ch(rhs.ch)
{
s = new char[strlen(rhs.s)+1];
strcpy(s,rhs.s);
}
const A& operator=(const A& rhs)
{
char *temp = new char[strlen(rhs.s)+1];
strcpy(temp,rhs.s);
delete[] s;
s=temp;
ch = rhs.ch;
return *this;
}
~A()
{
delete []s;
}
};
До этого момента все идет как положено. Я могу проверить свой конструктор копирования и оператор присваивания, и они работают правильно.
Теперь я создал дочерний класс B и получаю ошибку повреждения кучи. Я не могу понять, связана ли эта проблема где-то с деструктором класса А. ?
Ниже мой класс B,
class B:public A
{
public:
int a;
B():a(0){}
};
Вы конструктор по умолчанию для A
не инициализирует член s
(указатель):
A()
{}
Следовательно, когда элементы конструируются с использованием этого конструктора, вы получаете сбой, когда деструктор удаляет неинициализированный элемент:
~A()
{
delete []s;
}
Учебный класс B
использует конструктор по умолчанию для A
и, следовательно, вызывает эту проблему. Избегайте этого, правильно инициализируя все члены в конструкторе по умолчанию:
A() : ch(), s(0)
{ }
Чтобы решить вашу проблему, все что вам нужно сделать, это заменить:
char *s;
с
std::string s;
Просто избавьтесь от ручного управления памятью через char *
Именно поэтому C ++ предоставляет вам std::string
,
В чем может быть проблема?
Ваш конструктор по умолчанию, который не принимает никаких аргументов, не имеет динамического выделения.
Если вы создали объект класса с помощью этого конструктора, ваш деструктор заканчивается delete
указатель, который не был выделен new
и, таким образом, приводит к неопределенному поведению.
В деструкторе ты delete[] s;
, но в конструкторе по умолчанию вы не new[]
изд. На самом деле, вы даже не инициализировали s
,
Конструктор по умолчанию базового класса вызывается при создании экземпляра производного класса, поскольку в противном случае вы не инициализировали базовый класс (: A(...)
). Поэтому вы понятия не имеете, что вы удаляете, или даже то, что вы собираетесь есть на завтрак завтра, потому что это неопределенное поведение.
Чтобы это было согласованно, new[]
s в конструкторе по умолчанию. Чтобы избавиться от головной боли, я бы предложил что-то вроде std::string
вместо указателей персонажа.