Поведение наследования, когда класс включает конструктор копирования и оператор присваивания

Я не могу понять это поведение. У меня есть класс А,

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){}
};

1

Решение

Вы конструктор по умолчанию для A не инициализирует член s (указатель):

A()
{}

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

~A()
{
delete []s;
}

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

A() : ch(), s(0)
{ }
3

Другие решения

Чтобы решить вашу проблему, все что вам нужно сделать, это заменить:

char *s;

с

std::string s;

Просто избавьтесь от ручного управления памятью через char *Именно поэтому C ++ предоставляет вам std::string,

В чем может быть проблема?

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

3

В деструкторе ты delete[] s;, но в конструкторе по умолчанию вы не new[]изд. На самом деле, вы даже не инициализировали s,

Конструктор по умолчанию базового класса вызывается при создании экземпляра производного класса, поскольку в противном случае вы не инициализировали базовый класс (: A(...)). Поэтому вы понятия не имеете, что вы удаляете, или даже то, что вы собираетесь есть на завтрак завтра, потому что это неопределенное поведение.

Чтобы это было согласованно, new[] s в конструкторе по умолчанию. Чтобы избавиться от головной боли, я бы предложил что-то вроде std::string вместо указателей персонажа.

3
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector