Ошибки компоновщика GCC C ++: неопределенная ссылка на vtable for XXX, неопределенная ссылка на ClassName :: ClassName ()

Я настраиваю проект C ++, на Ubuntu x64, используя Eclipse-CDT. Я в основном делаю привет и делаю ссылки на коммерческую стороннюю библиотеку.

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

Is there a way to confirm the static libraries I am linking to are 64bit? Is there a way to confirm that the library has the class (and methods) I am expecting it to have?

Затмение говорит:

Building target: LinkProblem
Invoking: GCC C++ Linker
g++ -L/home/notroot/workspace/somelib-3/somelib/target/bin -o"LinkProblem"  ./src/LinkProblem.o   -lsomelib1 -lpthread -lsomelib2 -lsomelib3
./src/LinkProblem.o: In function `main':
/home/notroot/workspace/LinkProblem/Debug/../src/LinkProblem.cpp:17: undefined reference to `SomeClass::close()'
./src/LinkProblem.o: In function `SomeOtherClass':
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148: undefined reference to `SomeClass::SomeClass()'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148: undefined reference to `vtable for SomeOtherClass'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:151: undefined reference to `SomeClass::~SomeClass()'
./src/LinkProblem.o: In function `~SomeOtherClass':
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `vtable for SomeOtherClass'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `SomeClass::~SomeClass()'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `SomeClass::~SomeClass()'
collect2: ld returned 1 exit status
make: *** [LinkProblem] Error 1
 Alex Black08 июл. 2009 г., 01:13
Сторонние файлы lib находятся здесь: / home / notroot / workspace / somelib-3 / somelib / target / bin
 Alex Black08 июл. 2009 г., 01:07
Да, это 64 бит. Вы можете быть к чему-то, хотя. Как мне убедиться, что мой код / проект 64-битный? В Visual Studio я создал конфигурацию сборки x64.
 Daniel A. White08 июл. 2009 г., 01:11
Где он находится? Гугл показывает, что в / usr / lib64 есть полусоглашение
 Daniel A. White08 июл. 2009 г., 01:06
Является ли сторонняя библиотека 64-битной?
 Alex Black08 июл. 2009 г., 01:08
Есть ли способ подтвердить, что сторонняя библиотека является 64-битной? Например. проверять файлы .a инструментом или чем-то еще?

Ответы на вопрос(12)

убедитесь, что у вашего конструктора и деструктора базового класса есть тело, иначе компоновщик потерпит неудачу.

мир" как вещи с Qt. Проблемы ушли, правильно запустив qt moc (мета-объектный компилятор) и скомпилировав +, включая эти сгенерированные moc файлы правильно.

что вы переопределили виртуальную функцию в дочернем классе с помощью объявления, но не дали определения для метода. Например:

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

Но вы не дали определение f. Когда вы используете класс, вы получаете ошибку компоновщика. Подобно обычной ошибке компоновщика, это потому, что компилятор знал, о чем вы говорите, но компоновщик не смог найти определение. Просто получено очень трудное для понимания сообщение.

с виртуального интерфейса, а пользовательский класс, предоставляемый через разделяемую библиотеку, должен был реализовать интерфейс. При связывании приложения компоновщик жаловался, что совместно используемая библиотека не предоставляет vtable и type_info для базового класса, и их нельзя найти где-либо еще. Оказалось, что я просто забыл сделать один из методов интерфейса чисто виртуальным (т. Е. В конце объявления пропущен "= 0"). Очень элементарно, все еще легко пропустить и озадачивать, если вы не можете подключить компоновщик диагностическая причина.

Решение Вопроса

что эти методы находятся в одной из библиотек, это выглядит как проблема упорядочения.

При связывании библиотек в исполняемый файл они выполняются в порядке их объявления.
Кроме того, компоновщик будет использовать только те методы / функции, которые необходимы для разрешения текущих незавершенных зависимостей. Если последующая библиотека затем использует методы / функции, которые изначально не были необходимы объектам, у вас будут отсутствовать зависимости.

Как это устроено:

Take all the object files and combine them into an executable Resolve any dependencies among object files. For-each library in order: Check unresolved dependencies and see if the lib resolves them. If so load required part into the executable.

Пример:

Объекты требуют:

Open Close BatchRead BatchWrite

Lib 1 обеспечивает:

Open Close read write

Lib 2 обеспечивает

BatchRead (but uses lib1:read) BatchWrite (but uses lib1:write)

Если связаны, как это:

gcc -o plop plop.o -l1 -l2

Тогда компоновщик не сможет разрешить символы чтения и записи.

Но если я свяжу приложение так:

gcc -o plop plop.o -l2 -l1

Тогда это будет правильно связать. Поскольку l2 разрешает зависимости BatchRead и BatchWrite, а также добавляет две новые (чтение и запись). Когда мы свяжемся с l1 далее, все четыре зависимости будут разрешены.

когда вы измените класс таким образом, что он теперь наследуется от QObject (то есть, чтобы теперь он мог использовать сигналы / слоты). Запуск qmake -r вызовет moc и исправит эту проблему.

Если вы работаете с другими через какой-то контроль версий, вам нужно будет внести некоторые изменения в ваш файл .pro (т.е. добавить / удалить пустую строку). Когда все остальные получат ваши изменения и запустят make, make увидит, что файл .pro изменился, и автоматически запустит qmake. Это спасет ваших товарищей по команде от повторения вашего разочарования.

,

//-----------------------------------------
// libbase.h
class base {
public:
   base() { }
   virtual ~base() { }

   virtual int foo() { return 0; }
};
//-----------------------------------------

//-----------------------------------------
// libbase.cpp
#include "libbase.h"
//-----------------------------------------

//-----------------------------------------
// main.h
class derived : public base {
public:
    virtual int foo() ;
};
//-----------------------------------------

//-----------------------------------------
// main.cpp
int main () {
    derived d;
}
//-----------------------------------------

Проблема в компоновщике. Мой заголовочный файл где-то находился в библиотеке, но все виртуальные функции были объявлены как «встроенные». в объявлении класса. Поскольку не было кода, использующего виртуальные функции (пока), компилятор или компоновщик пренебрегали размещением реальных тел функций на месте. Также не удалось создать vtable.

В моем основном коде, где я получил этот класс, компоновщик пытался соединить мой класс с базовым классом и его vtable. Но vtable был отброшен.

Решением было объявить хотя бы одну из виртуальных функций & apos; тела вне объявления класса, вот так:

//-----------------------------------------
// libbase.h
class base {
public:
   base() { }
   virtual ~base() ;   //-- No longer declared 'inline'

   virtual int foo() { return 0; }
};
//-----------------------------------------

//-----------------------------------------
// libbase.cpp
#include "libbase.h"
base::~base() 
{
}
//-----------------------------------------

что я объявил виртуальный деструктор в заголовочном файле & # xFF0C; но виртуальные функции & apos; тело на самом деле не было реализовано.

когда мы просто объявляем виртуальную функцию без какого-либо определения в базовом классе.

Например:

class Base
{
    virtual void method1(); // throws undefined reference error.

}

Измените вышеупомянутое объявление на следующее, оно будет работать нормально.

class Base
{
    virtual void method1()
    {
    }
}

если вы получаете сообщение об ошибке при созданииException объект, то причиной этого, вероятно, является отсутствие определенияwhat() виртуальная функция.

когда я забыл добавить = 0 для одной функции в моем чистом виртуальном классе. Это было исправлено, когда был добавлен = 0. Так же, как для Фрэнка выше.

class ISettings
{
public: 
    virtual ~ISettings() {};
    virtual void OKFunction() =0;
    virtual void ProblemFunction(); // missing =0   
};

class Settings : ISettings
{
    virtual ~Settings() {};
    void OKFunction();
    void ProblemFunction(); 
};

void Settings::OKFunction()
{
    //stuff
}

void Settings::ProblemFunction()
{
    //stuff
}

я не могу использовать опцию qmake moc, упомянутую выше. Но это не было проблемой в любом случае. У меня был следующий код в определении класса:

class ScreenWidget : public QGLWidget
{
   Q_OBJECT        // must include this if you use Qt signals/slots
...
};

Мне пришлось удалить строку "Q_OBJECT" потому что у меня не было определенных сигналов или слотов.

Ваш ответ на вопрос