Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Опять undefined reference to

446
12 сентября 2013 года
Meander
487 / / 04.09.2011
Как обычно делал проект в Dev-Cpp. Добавил к нему файлы заголовка и реализации, а в main.cpp добавил директиву о включении файла заголовка. Во включенных файлах реализован обычный класс, а в main.cpp использую интерфейс класса. Если компилировать так, то выдает ошибки:
[Linker error] main.o:main.cpp:(.text+0x121): undefined reference to `имя функции члена'
для некоторых функций-членов (хотя в main.cpp вызываю все), причем сигнатура тех функций к которым нет претензий такая-же как у неопределенных линковщиком.
Если перенести текст из файла реализации в main.cpp, то компилируется нормально.

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

Объясните мне, что происходит.
446
17 сентября 2013 года
Meander
487 / / 04.09.2011
Все определения методов класса, который я использовал, предварялись модификатором inline на всякий случай. Если в main вызывать эти функции, то возникала ошибка Linker error. Когда были убраны модификаторы у проблемных функций все скомпилировалось. Это очень странно, не знал о таком поведении.

Код:
//test.h
class A {
  private:
    void Foo1(void);
  public:
    void Foo2(void);
    void Foo3(void);
};

//test.cpp
#include "test.h"

inline void A::Foo1(void){
  //code ...
}

inline void A::Foo2(void){
  Foo1();
}

void A::Foo3(void){
  Foo1();
}

//main.cpp
#include "test.h"

int main(int argc, char *argv[]){
  A a;
  a.Foo2();// [Linker error] ... undefined reference to `A::Foo2(void)'
  a.Foo3();// Ok!
  return 0;
}
412
13 сентября 2013 года
grgdvo
323 / / 04.07.2007
Обратите внимание, что у вас Linker error. То есть стадия компиляция прошла успешно, осталась только линковка.
Нужно смотреть команду линковки, которую формирует ваша среда разработки. От этого плясать.
Может быть среда косячит, а может и порядок при линковке важен...
8
13 сентября 2013 года
mfender
3.5K / / 15.06.2005
А там дебугера нет разве? Не будучи осведомлённым в ваших IDE, могу сразу предположить, что объект не создан, и дело тут вовсе не в IDE. Курите свой текст лучше, ошибка происходит на стадии создания объекта.
326
17 сентября 2013 года
sadovoya
757 / / 19.11.2005
А где в определниях расширение A:: ? Оно нужно.
446
17 сентября 2013 года
Meander
487 / / 04.09.2011
Цитата: sadovoya
А где в определниях расширение A:: ? Оно нужно.


Да, спасибо, пропустил (код не копипастил). Исправлю.

326
17 сентября 2013 года
sadovoya
757 / / 19.11.2005
Множественного включения заголовков нет?
446
17 сентября 2013 года
Meander
487 / / 04.09.2011
В моем рабочем коде есть и там использую макро команды для невключения. Но в этом примере они, по-моему не требуются.
326
17 сентября 2013 года
sadovoya
757 / / 19.11.2005
Тогда дичь какая-то. Что за компилятор?
446
17 сентября 2013 года
Meander
487 / / 04.09.2011
Цитата: sadovoya
Тогда дичь какая-то. Что за компилятор?


MinGW 4.7.2 (шел вместе с Dev-Cpp). Но и в Borland то-же, только unresolved external.

326
17 сентября 2013 года
sadovoya
757 / / 19.11.2005
Прикольно. У меня тоже MinGW, ничего подобного не наблюдалось. Еще и в билдере.. Даже на среду не похоже.
446
17 сентября 2013 года
Meander
487 / / 04.09.2011
Цитата: sadovoya
Прикольно. У меня тоже MinGW, ничего подобного не наблюдалось. Еще и в билдере.. Даже на среду не похоже.


Сейчас проверил свой код (из этого поста), как и говорил ошибка есть.

326
17 сентября 2013 года
sadovoya
757 / / 19.11.2005
А с путями все нормально, файлы в той-же папке, что main? Кстати иногда с русскими папками проблемы бывают.
446
17 сентября 2013 года
Meander
487 / / 04.09.2011
Цитата: sadovoya
А с путями все нормально, файлы в той-же папке, что main?


Разумеется.
Вообще недавно прочитал, что inline функции могут быть встроены, когда объявляются в той же единице трансляции где используются. Так что если перенести текст из test.cpp в main.cpp то проблема исчезнет.

326
17 сентября 2013 года
sadovoya
757 / / 19.11.2005
Единицей трансляции будет и так пара h и cpp по-моему. Еще в классах инлайнится либо, если определение сразу при объявлении в классе, либо с модификатором inline как у вас. Насчет единицы трансляции что-то сам уже засомневался.
446
17 сентября 2013 года
Meander
487 / / 04.09.2011
Цитата: sadovoya
Единицей трансляции будет и так пара h и cpp по-моему. Еще в классах инлайнится либо, если определение сразу при объявлении в классе, либо с модификатором inline как у вас.


Да, но ведь Foo2 вызывается в main. А к Foo1, вообще претензий нет. Кроме того, управлять компиляцией inlain функций можно ключами компилятора, но у меня все по умолчанию.

326
17 сентября 2013 года
sadovoya
757 / / 19.11.2005
Проблема действительно в inline. Порылся в сети, у многих проблема при описании в cpp. Еще узнал, что некотрые компиляторы умеют правильно находить их в cpp, но на это тратится время, и зависит от настроек. В основном рекомендуют описывать в хедере. Хуже вариант - описывать во всех единицх трансляции, которые их используют.
98K
04 сентября 2016 года
ivan.vo
1 / / 04.09.2016
С линковкой inline методов - всё логично. Большинство стандартов С++ содержат такое требование: описывайте (реализацию) inline метода в заголовочном файле. Совсем не обязательно это делать в теле класса. Это в некоторых случаях ухудшает читабельность структуры. Если всё таки Вам хочется вынести реализацию в другой файл, то такая возможность существует. Вы можете сделать, например, так (это не догма, но - принцип):
1. Создать файл с именем как заголовок, но с расширением ".inl" (так поступают большинство корпоративных разработчиков).
2. В этом файле разместить реализацию громоздких методов.
3. Для подсоединения созданного файла к заголовку в конце заголовочного файла указать директиву
#include "<Имя заголовка>.inl"
Лично я рекомендую эту директиву применять в завершении пространства имен (namespace).
Повторюсь - это не догма. "Инлайн" файл может иметь отличное от заголовка название и "цепляться" разными заголовками. Всё зависит от применения.
Следует также помнить, что "ругательство" inline, по своей сути, рудимент. Большинство компиляторов (современных) будет использовать этот принцип (inline) в том случае, если вы располагаете реализацию метода в заголовке. В некоторых компиляторах - это регулируется ключами.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог