Передача переменной в конструктор производному классу дает значение мусора, и конструкторы базового и производного класса имеют разные параметры. Почему? - PullRequest
0 голосов
/ 30 апреля 2020

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

При передаче переменной в конструктор производного класса он дает значение мусора при объявлении массива базового класса. Размер массива не 'n', а какое-то мусорное значение.

class LinkedList{
public:
    Node* head;
    LinkedList()
    {
        cout << "c";
        head=NULL;          
    }
};
class hashing : public LinkedList{
public:
    int n;
    hashing(int num)
    {
        this->n=num;
    }
    LinkedList* l = new LinkedList[n];
    void iterateL()
    {
        for(int i=0; i<n; i++)
        {
             l[i].head=NULL;
             cout << i << endl;
        }
    }
};
int main() 
{
int n=7;
hashing op(n);
}

Ожидается, что l oop внутри класса хеширования будет выполняться 7 раз, но после запуска 4 раза выдает ошибку.

Ответы [ 3 ]

2 голосов
/ 01 мая 2020

Хорошо, проблема здесь тонкая (до такой степени, что я сначала не видел проблему).

Проблема в том, что вы инициализируете, используя значение n (this->n) во время инициализации члена класса.

Проблема в том, что в C ++ все эти инициализаторы запускаются во время члена инициализация, предшествующая телу конструктора. Поскольку вы не устанавливаете значение this->n до тех пор, пока тело конструктора не будет инициализировано this->n

Другими словами, то, что у вас есть, равнозначно написанию

hasing(int num): l(new LinkedList[n]) {
   this->n = num;
}

Это происходит потому, что по умолчанию все члены инициализируются в порядке, указанном в классе, при необходимости заменяя инициализаторы членов по умолчанию (выражение после = в определении класса).

Существует несколько решения:

Использование инициализатора элемента

hashing(int num): n(num),l(new LinkedList[n])
{

}

Использование тела конструктора:

hashing(int num)
{
   this->n = num;
   this->l = new LinkedList[n];
}

В обоих В вышеуказанных случаях я бы не стал указывать спецификатор члена по умолчанию. Я бы просто объявил указатель.

LinkedList* l; // No default member initializer

Наконец, я бы позаботился о том, чтобы вы правильно обрабатывали уничтожение и копирование / перемещение назначения.

1 голос
/ 01 мая 2020

Когда тело конструктора получает управление, все нестатические c члены класса уже созданы.

Таким образом, этот элемент данных

LinkedList* l = new LinkedList[n];

уже был создан с использованием неопределенное значение элемента данных n.

Перепишите конструктор следующим образом

hashing(int num) : n( num )
{
}

Обратите внимание, что нет смысла объявлять хеширование класса как производный класс LinkedList, потому что одновременно вы также используете композицию

1 голос
/ 30 апреля 2020

Ваш hashing конструктор должен выглядеть следующим образом:

hashing(int num)
{
   this->n=num;
   l = new LinkedList[n];   // allocate once 'n' is known
}

в противном случае вы не выделяете достаточно элементов в l. Фактически, вы выделяете n элементов, но поскольку n не имеет значения по умолчанию, это мусор и использование UB.

Значением по умолчанию для l может быть просто:

LinkedList* l = nullptr;

Конечно, обязательно удалите память в деструкторе:

~hashing() 
{
  delete [] l;
}
...