Собираете эдак вы значит какой-нибудь архи-важный проект. Витаете где-то в высоких абстракциях. А то и озадачиваетесь вопросами бизнес-логики. И тут билд валится. С формулировкой:
error LNK2005: some_func already defined in some_file.obj или some_file.cpp: multiple definition of some_func(). Вполне может быть, что эту самую функцию some_func() вы лично и в глаза то не видели, и не трогали, и ваще – какого ???
Что делать?
Ищете заголовочный файл с этой функцией.
Находите там кроме заголовка функции (или метода класса) еще и ее определение.
Если есть библиотека/объектник с искомой функцией, которую вы линкуете к своему проекту – комментируете определение в заголовочном файле. Если нет – пишите перед заголовком слово inline. Если там весь из себя c++ с классами, методы которых за каким-то лешим определены чуть ниже объявления класса (см method_A в примере ниже) – выносите их в соответствующий .cpp файл, добавляя его в сборку. Для успеха сборки будет достаточно запихнуть определение в описание класса – но как то это не по людски.Собираете проект, находите виновного и тыкаете ему в нос ниженаписанное:
Почему нежелательно в заголовочных файлах определять функции (методы).
Представьте что у вас есть такой вот хедер: header_example.h
#ifndef MY_HEADER #define MY_HEADER #include <iostream> using namespace std; inline void my_func_1() { cout << "my_func_1" << endl; }; int my_func_2(int arg1, int arg2) { cout << "my_func_2"<<endl; return arg1+arg2; }; class A { public: virtual ~A(){/* some implementation here*/}; void method_A(); }; void A::method_A() { // some very usefull code here } #endif
предположим, эти функции всю жизнь дергались исключительно из файлика: additional.cpp
#include "header_example.h" void one_more_func() { my_func_1(); };
и все было хорошо до тех пор пока их не решили задействовать в дополнительном модуле: main.cpp
#include "header_example.h" void one_more_func(); int main(int argc, char* argv[]) { cout << "main " << endl; one_more_func(); return 0; }
мейкфайл для всего этого добра выглядит так: Makefile
CC = g++ OBJS = main.o additional.o all: test_exec test_exec: $(OBJS) $(CC) -o test_exec $(OBJS) %.o: %.cpp $(CC) -c $< -o $@ clean: rm -f *.o rm -f test_exec
при попытке сборке линковщик озадаченно сетует:
additional.o: In function `A::method_A()’:
additional.cpp:(.text+0x0): multiple definition of `A::method_A()’
main.o:main.cpp:(.text+0x0): first defined here
additional.o: In function `my_func_2(int, int)’:
additional.cpp:(.text+0xb): multiple definition of `my_func_2(int, int)’
main.o:main.cpp:(.text+0x0): first defined here
collect2: ld returned 1 exit
что слишком много развелось функций по имени my_func_2(int, int). А мы ведь помним что такое хедеры и что значит строки #include “my_header.h” или #include “my_source.cpp”? Линкеру на вход подается два объектных файла, содержащих описаную в хедере функцию. Только его никто не предупредил что эта функция, вообще-то, одна и та же, а сам он не в силах уразуметь которую из них ему использовать при линковке.
Мораль – оставляйте в заголовочных файлах только заголовки функций, их определение – выносите в *.cpp/*.c.
3 comments
Спасибо за пост!
спасибо, очень помогли
Огромнейшее спасибо!!! Очень помогли!! И главное так доходчиво объяснили!! Облазили кучу сайтов и форумов, у многих возникает такая ошибка, и люди то хотят объяснить, как решить эту проблему, но не могут, либо, могут, но не хотят!! То есть по делу ничего не пишут, а только умничают! Ещё раз спасибо!