G ++ дает ошибки, где Visual Studio был счастлив - неопределенная ссылка - PullRequest
1 голос
/ 04 марта 2011

У меня есть код, который отлично работает в Visual Studio, и сейчас я пытаюсь скомпилировать его на g ++.Он дает мне «неопределенную ссылку на SomeClass :: someMethod () const» в нескольких местах.

Чаще всего это следующая ситуация:

for (const SomeListNode *node = owner->some_list; node != 0; node = node->getNext())

В этом случае яполучить 'неопределенную ссылку на SomeListNode :: getNext () const'.Заголовочный файл этого класса явно включен.Почему это не разрешено в g ++?

для получения дополнительной информации отредактируйте

Я строю с помощью make-файла следующим образом:

CC=g++
CFLAGS=-c -Wall -DDEBUG -g
LDFLAGS=
SOURCES=main.cpp SomeList.cpp SomeListNode.cpp Location.cpp OutputControl.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=theprogram

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(LDFLAGS) $(OBJECTS) -o $@

.cpp.o: $ (CC) $ (CFLAGS) $ <-o $ @ </p>

Первоначально указанная строка кода указана в OutputControl.cpp.Он берет указатель на SomeListNode и перебирает его.getNext () возвращает указатель на другой SomeListNode.

Также следует отметить, что это происходит только в статических функциях.

Ответы [ 6 ]

2 голосов
/ 04 марта 2011

Вы можете вызывать const-квалифицированные методы только для const-квалифицированного объекта.Если getNext () не является константой, тогда вы должны использовать SomeListNode *node вместо const SomeListNode *node.

1 голос
/ 04 марта 2011

Я бы посоветовал вам установить зависимости в вашем make-файле, чтобы объекты, зависящие от других, создавались в правильном порядке.Также установите чистую цель, которая удаляет файлы .o.После этого беги зачисти и сделай.

Это лучшее предложение, которое я могу придумать с информацией, которую вы нам дали.

1 голос
/ 04 марта 2011

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

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

В любом случае, скомпилируйте каждый объектный файл отдельно в .o или библиотеку и используйте nm, чтобы извлечь список символов, который определен в каждой из единиц перевода, который должен сказать вам, было ли определение скомпилировано или нет и поможет вам определить порядок, если вы компилируете статические библиотеки.

0 голосов
/ 24 марта 2012

Разница между Visual Studio и g ++ заключается в том, как они работают с шаблонами. В Visual Studio, если вы определяете функцию в шаблоне, но никогда нигде ее не используете, VS не проверяет ее тип и не генерирует какой-либо код. В g ++ он проверит тип (и даст вам ошибки, если в нем есть какие-либо проблемы).

0 голосов
/ 04 марта 2011

Я рекомендую использовать инструмент nm, чтобы выяснить, какие символы участвуют в вашей ситуации. Это может выглядеть так:

// foo.h
class Foo{
    public:
        void bar();
};

// foo.cpp
#include "foo.h"
void Foo::bar()
{
}

// bar.cpp
#include "foo.h"
void baz()
{
    Foo f;
    f.bar();
}

> nm foo.o
00000000 T _ZN3Foo3barEv

> nm bar.o
00000000 T _Z3bazv
         U _ZN3Foo3barEv
         U __gxx_personality_v0

Здесь вы можете видеть, что bar.o использует неопределенный символ _ZN3Foo3barEv__gxx_personality_v0, но это деталь компилятора), который помечен U. Этот символ определен в foo.o, где он помечен T. Чтобы получить имя c ++ из искаженного имени, вы можете использовать c++filt.

> c++filt _ZN3Foo3barEv
Foo::bar()

> c++filt _Z3bazv
baz()

Для устранения проблемы вы проверяете файлы SomeList.o и OutputControl.o и ищете экземпляры SomeListNode :: getNext. Выводов может быть много, поэтому вы можете отфильтровать вывод с помощью nm file.o | grep 'SomeListNode.*getNext'. Каждый U отмеченный SomeListNode::getNext символ из вашего файла OutputControl.o должен иметь точное совпадение в вашем файле SomeList.o.

Редактировать : Скорректированный ответ на опубликованный Makefile.

0 голосов
/ 04 марта 2011

Передайте все ваши файлы .cpp команде g ++ compile.

g++ -g -Wall -o myapp File1.cpp File2.cpp File3.cpp

EDIT:

Если вы используете статические библиотеки, вы должны добавить эти last в командной строке g ++.

Компоновщик обрабатывает переданные файлы по порядку, и когда он сталкивается со статической библиотекой, он ищет символы, которые пока не определены . Вы можете изменить это, используя --whole-archive

...