c ++ неопределенная ссылка на vtable - PullRequest
16 голосов
/ 25 ноября 2010

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

==> BasicMath.h <==
#ifndef BASIC_MATH_H
#define BASIC_MATH_H

#include<string>
#include<vector>    

class BasicMath { };


#endif // BASIC_MATH_H

==> Operation.h <==

#ifndef OPERATION
#define OPERATION

#include<string>
#include<vector>    

class Operation {
 public:
  virtual void perform(std::vector<std::string> vec) = 0;
};


#endif // OPERATION

==> Sum.h <==
#ifndef SUM_H
#define SUM_H

#include "Operation.h"

class Sum: public Operation {
 public:
  void perform(std::vector<std::string> vec);
};

#endif // SUM_H

==> BasicMath.cpp <==
#ifndef BASIC_MATH_C
#define BASIC_MATH_C

#include <string>
#include <vector>
#include <iostream>
#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 <vector>
#include <string>
#include <iostream>
#include "Sum.h"

void Sum::perform(std::vector<std::string> 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% уверен, что я делаю здесь хотя бы одну глупую вещьно мой мозг отказывается сказать мне, что.

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

Ответы [ 6 ]

24 голосов
/ 19 июня 2013

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

class.h:

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

class.cpp:

MyClass::MyClass() {}

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

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

MyClass::MyClass() {}
MyClass::~MyClass() {}
16 голосов
/ 25 ноября 2010

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

6 голосов
/ 25 ноября 2010

Несколько человек уже указали решение проблемы, с которой вы столкнулись.

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

//#ifndef SUM_C
//#define SUM_C
//
#include <vector>
#include <string>
#include <iostream>
#include "Sum.h"

void Sum::perform(std::vector<std::string> 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<std::string> vec) = 0;
};

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

Sum op;
op.perform();

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

Sum op;
op();

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

3 голосов

Эта ошибка также происходит, если вы забыли = 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.

1 голос
/ 25 ноября 2010

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

1 голос
/ 25 ноября 2010

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

...