Это сообщение об ошибке выскочило для меня сегодня, когда я находился в процессе кодирования производного класса, и в моем случае ключом было то, что производный класс был - в тот момент - неинстанцибельным. 1
Как только я добился достаточного прогресса в производном классе, чтобы его можно было создать, ошибки испарились.
Причина
Производный вызов, из которого вы печатаете, чтобы вызвать базовый класс, в настоящее время не может быть создан.
Демонстрация
Рассмотрим следующий код, который имеет два отношения наследования.
class Type {
public:
Type(){}
virtual ~Type() {}
virtual void m() = 0;
};
class SubType: public Type {
public:
SubType(): Type() {}
virtual ~SubType() {}
// virtual void m() override; // <== Important code commented out here
};
// void SubType::m() {} // <== and here
class Base {
public:
Base() {};
virtual ~Base() {}
virtual void m();
};
class Derived: public Base, public Type {
public:
Derived(): Base() {}
virtual ~Derived() override {}
virtual void m() override;
protected:
SubType m_troublesome; // <== Note member here has incomplete type when
// comments are in place
};
void Base::m() {}
void Derived::m() {
Base::m(); // <== Tricky error message on this line
}
Попытка скомпилировать это с
$ clang --std=c++11 -Wall -pedantic -c test.cc
и вы получите отзыв
test.cc:34:13: error: field type 'SubType' is an abstract class
SubType m_troublesome;
^
test.cc:8:18: note: unimplemented pure virtual method 'm' in 'SubType'
virtual void m() = 0;
^
test.cc:42:11: error: cannot initialize object parameter of type 'Base' with an
expression of type 'Derived'
Base::m();
Если вы видите все три вместе, вы знаете, с чего начать, но если вы используете clang в качестве линтера (как это делают многие IDE), то вы можете увидеть третий (который встречается в строке Base::m();
, совершенно допустимый фрагмент кода) в контексте, отделенном от первых двух.
Мгновенное замешательство.
Если вы удалите комментарии из двух отмеченных разделов кода (сделав SubType
завершенным и, таким образом, сделав возможным создание экземпляров Derived
объектов), код скомпилируется чисто.
Два возможных урока здесь:
- Завершите то, что вы начали. Если бы я не оставил аналог
SubType
наполовину готовым, ситуация никогда бы не возникла.
- Если линтер сбивает с толку, посмотрите полный вывод ошибок сборки.
1 В частности, у меня был объявлен элемент с типом, в котором я еще не переопределил унаследованный абстрактный виртуальный метод.