c ++ неопределенная ссылка на vtable

Я изучаю C ++. Я пытаюсь выполнить упражнение, когда я определяю несколько реализаций чистого виртуального classа с одной функцией. У меня возникли проблемы с привязкой classа, который использует эти реализации.

==> BasicMath.h <== #ifndef BASIC_MATH_H #define BASIC_MATH_H #include #include class BasicMath { }; #endif // BASIC_MATH_H ==> Operation.h <== #ifndef OPERATION #define OPERATION #include #include class Operation { public: virtual void perform(std::vector vec) = 0; }; #endif // OPERATION ==> Sum.h <== #ifndef SUM_H #define SUM_H #include "Operation.h" class Sum: public Operation { public: void perform(std::vector vec); }; #endif // SUM_H ==> BasicMath.cpp <== #ifndef BASIC_MATH_C #define BASIC_MATH_C #include  #include  #include  #include "BasicMath.h" #include "Sum.h" int main(int argc, char* argv[]) { Sum op; } #endif // BASIC_MATH_C ==> Sum.cpp <== #ifndef SUM_C #define SUM_C #include  #include  #include  #include "Sum.h" void Sum::perform(std::vector vec) { using namespace std; int total = 0; cout << "Total: " << total << "\n"; }; #endif // SUM_C 

Компиляция:

 $ g++ -c Sum.cpp $ g++ -o BasicMath BasicMath.cpp /tmp/cc1VXjNl.o:BasicMath.cpp:(.text$_ZN3SumC1Ev[Sum::Sum()]+0x16): undefined reference to `vtable for Sum' collect2: ld returned 1 exit status 

Я на 95% уверен, что делаю по крайней мере одну глупость здесь, но мой мозг отказывается мне что-то сказать.

Я вижу этот вопрос, но не смог исправить свою проблему.

Вы не включаете объектный файл Sum.o в свою линию компиляции и ссылки (второе использование g ++).

Я просто столкнулся с той же проблемой, но моя проблема заключалась в том, что я не написал код деструктора в моем файле .cpp.

class.h:

 class MyClass { public: MyClass(); virtual ~MyClass(); }; 

class.cpp:

 MyClass::MyClass() {} 

Он просто дал мне сообщение об ошибке vtable, и реализация (пустой) деструктора решила проблему.

[Edit] Таким образом, исправленный файл classа выглядит следующим образом:

 MyClass::MyClass() {} MyClass::~MyClass() {} 

Пара людей уже указала на решение проблемы, которую вы видели.

Я добавлю что-то совсем другое. Вам нужны только защитники заголовков в ваших заголовках. Вы включили их в свои исходные файлы , где они действительно не имеют смысла. Например, я прокомментировал строки, которые вам действительно не нужны (или даже хотят) в sum.cpp:

 //#ifndef SUM_C //#define SUM_C // #include  #include  #include  #include "Sum.h" void Sum::perform(std::vector vec) { using namespace std; int total = 0; cout << "Total: " << total << "\n"; }; //#endif // SUM_C 

Просто FWIW, вместо perform , я бы использовал operator() :

 class Operation { public: virtual void operator()(std::vector vec) = 0; }; 

и (очевидно), это также то, что вы перегрузили для Sum . Чтобы использовать его, вместо чего-то вроде:

 Sum op; op.perform(); 

Вы бы использовали что-то вроде:

 Sum op; op(); 

Это особенно удобно, когда вы совмещаете свой class с другими (например, те, что входят в стандартную библиотеку), которые вызывают операции, такие как функции, независимо от того, действительно ли они функционируют или «функторы» (такие classы, как this, что перегружает operator() так синтаксически они могут использоваться почти как функции).

Эта ошибка также возникает, если вы забываете = 0 для чистых виртуальных функций

Ошибка:

 class Base { public: virtual void f(); }; class Derived : public Base { public: virtual void f() {} }; int main() { Derived d; Base *b = &d; } 

Нет ошибки:

 class Base { public: virtual void f() = 0; }; 

Это связано с тем, что без = 0 , C ++ не знает, что это чистая виртуальная функция, рассматривает его как объявление, ожидая более позднего определения.

Протестировано по g++ 5.2.1.

Вы просто компилируете BasicMath.cpp без Sum.cpp – ваш компоновщик понятия не имеет о Sum.cpp. Вам нужно будет скомпилировать их оба вместе, то есть Sum.cpp BasicMath.cpp за один раз, или вы можете самостоятельно скомпилировать файлы .cpp, а затем создать исполняемый файл, вызвав g ++ с обоими файлами .o.

Обычно я сталкиваюсь с этой ошибкой, когда случайно забываю =0 в конце одной из моих функций в чистом виртуальном classе.

  • gcc / g ++ для размещения всех объектных файлов в отдельном каталоге
  • Почему мне нужно использовать typedef typename в g ++, но не VS?
  • g ++ «вызывает» функцию без скобок (не f (), но f;). Почему он всегда возвращает 1?
  • Ошибка времени компиляции C ++: ожидаемый идентификатор до числовой константы
  • В объектном файле слишком много разделов
  • Различные результаты с плавающей запятой с включенной оптимизацией - ошибка компилятора?
  • Как включить путь к библиотекам в g ++
  • Неопределенная ссылка на статический член classа
  • constexpr инициализирует статический член, используя статическую функцию
  • Почему происходит отключение функции не-void без возврата значения, не приводящего к ошибке компилятора?
  • Ошибка: free (): недопустимый следующий размер (быстрый):
  • Давайте будем гением компьютера.