Как разрешить "чистый виртуальный метод, называемый"
Я понимаю, почему это происходит, но я застреваю, пытаясь его решить... вот что мой код делает, когда генерируется ошибка (таким образом, приводя к сбою), когда моя программа выходит...
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*>
.
Ответы
Ответ 1
К тому времени, когда вы вызываете деструктор, деструктор унаследованных классов уже вызван. Внутри конструкторов и деструкторов динамический тип объекта можно эффективно рассматривать как то же, что и статический тип. То есть, когда вы вызываете виртуальные методы из своих конструкторов/деструкторов, это не переопределенные версии их, которые вызывают.
Если SomePureVirtualMethod
нужно вызвать в деструкторе, вы должны будете вызвать его в деструкторе класса, где фактическое определение метода вы хотите.
Ответ 2
Когда вы вызываете метод virtual
в деструкторе базового класса SomeClass
, он вызывает метод (SomePureVirtualMethod()
) базового класса SomeClass
, который является чистым виртуальным методом без определения. И, следовательно, ошибка.
Почему это происходит?
Тип this
в конструкторе или деструкторе относится к типу, конструктор или деструктор которого вызывается и, следовательно, динамическая диспетчеризация не работает в конструкторах и деструкторах, как вы ожидали бы, что она будет работать во всех других функциях.
Почему он падает?
Поскольку вызов чистой виртуальной функции из конструктора или деструктора - это Undefined Поведение.
С++ 03 10.4/6 состояний
"Функции-члены могут быть вызваны из конструктора (или деструктора) абстрактного класса, эффект виртуального вызова (10.3) на чистую виртуальную функцию, прямо или косвенно, для создаваемого (или уничтоженного) объекта из таких конструктор (или деструктор) undefined."
Как его избежать?
Просто убедитесь, что вы не называете чистую виртуальную функцию от конструктора или деструктора.
Не вызывайте virtual
методы в конструкторе или деструкторе, если вы не понимаете динамику.