Ошибка линковки: some_func already defined in some_file.obj или some_file.cpp: multiple definition of some_func

Собираете эдак вы значит какой-нибудь архи-важный проект. Витаете где-то в высоких абстракциях. А то и озадачиваетесь вопросами бизнес-логики. И тут билд валится. С формулировкой:
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

    • Pavel on January 26, 2013 at 3:43 pm
    • Reply

    Спасибо за пост!

    • Karina on June 25, 2013 at 1:03 pm
    • Reply

    спасибо, очень помогли

    • Yulia i Dima on May 12, 2014 at 2:02 am
    • Reply

    Огромнейшее спасибо!!! Очень помогли!! И главное так доходчиво объяснили!! Облазили кучу сайтов и форумов, у многих возникает такая ошибка, и люди то хотят объяснить, как решить эту проблему, но не могут, либо, могут, но не хотят!! То есть по делу ничего не пишут, а только умничают! Ещё раз спасибо!

Leave a Reply

Your email address will not be published.