Подтвердить что ты не робот

Как разрешить "чистый виртуальный метод, называемый"

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

pure virtual method called

SomeClass::~SomeClass()
{
   BaseClassObject->SomePureVirtualMethod(this);
}

void DerivedClass::SomePureVirtualMethod(SomeClass* obj)
{
    //Do stuff to remove obj from a collection
}

У меня никогда не было вызова new SomeClass, но у меня есть QList<SomeClass*>, к которому я добавляю объекты SomeClass*. Цель этого деструктора в SomeClass - сообщить DerivedClass удалить конкретный экземпляр SomeClass из его коллекции QList<SomeClass*>.

Итак, в конкретном примере...

BaseClass= Shape

DerivedClass= Triangle

SomeClass= ShapeProperties, которому принадлежит ссылка на Shape

Итак, я никогда не звоню в new ShapeProperties, но у меня есть QList<ShapeProperties*> внутри Triangle. Деструктор в ShapeProperties должен сообщить Triangle удалить определенное свойство ShapeProperties из его коллекции QList<ShapeProperties*>.

4b9b3361

Ответ 1

К тому времени, когда вы вызываете деструктор, деструктор унаследованных классов уже вызван. Внутри конструкторов и деструкторов динамический тип объекта можно эффективно рассматривать как то же, что и статический тип. То есть, когда вы вызываете виртуальные методы из своих конструкторов/деструкторов, это не переопределенные версии их, которые вызывают.

Если SomePureVirtualMethod нужно вызвать в деструкторе, вы должны будете вызвать его в деструкторе класса, где фактическое определение метода вы хотите.

Ответ 2

Когда вы вызываете метод virtual в деструкторе базового класса SomeClass, он вызывает метод (SomePureVirtualMethod()) базового класса SomeClass, который является чистым виртуальным методом без определения. И, следовательно, ошибка.

Почему это происходит?
Тип this в конструкторе или деструкторе относится к типу, конструктор или деструктор которого вызывается и, следовательно, динамическая диспетчеризация не работает в конструкторах и деструкторах, как вы ожидали бы, что она будет работать во всех других функциях.

Почему он падает?
Поскольку вызов чистой виртуальной функции из конструктора или деструктора - это Undefined Поведение.

С++ 03 10.4/6 состояний

"Функции-члены могут быть вызваны из конструктора (или деструктора) абстрактного класса, эффект виртуального вызова (10.3) на чистую виртуальную функцию, прямо или косвенно, для создаваемого (или уничтоженного) объекта из таких конструктор (или деструктор) undefined."

Как его избежать?
Просто убедитесь, что вы не называете чистую виртуальную функцию от конструктора или деструктора.
Не вызывайте virtual методы в конструкторе или деструкторе, если вы не понимаете динамику.