Одной из возможных причин является то, что вы объявляете виртуальную функцию, не определяя ее.
Когда вы объявляете это, не определяя его в том же модуле компиляции, вы указываете, что он определен где-то еще - это означает, что фаза компоновщика попытается найти его в одном из других модулей (или библиотек) компиляции.
Пример определения виртуальной функции:
virtual void fn() { /* insert code here */ }
В этом случае вы присоединяете определение к объявлению, что означает, что компоновщику не нужно разрешать его позже.
Линия
virtual void fn();
объявляет fn()
без его определения и вызывает сообщение об ошибке, о котором вы спрашивали.
Это очень похоже на код:
extern int i;
int *pi = &i;
, в котором указано, что целое число i
объявлено в другом модуле компиляции, который должен быть разрешен во время соединения (в противном случае pi
не может быть установлен по его адресу).