Coding Memo

[LNK2005] already defined in ~~.obj / inline 함수 본문

Language/C++

[LNK2005] already defined in ~~.obj / inline 함수

minttea25 2024. 10. 28. 18:49

먼저, 이 포스팅을 작성하게된 이유는 헤더 파일에 있는 함수들은 모두 암묵적으로 inline화가 되는 줄 착각하고 있던 내 생각때문이다...

 

결론만 먼저 말하면...

클래스 외부에서 함수의 body를 정의할 때는 inline을 명시적으로 추가하지 않는 이상, 암묵적으로 inline으로 간주되지 않는다.


 

내가 직면한 링킹에러는 LNK2005 에러로, 다음 내용이다.

[~~~~] already defined in [~~~].obj

 

어떤 함수가 어떤 클래스의 오브젝트 파일에 이미 정의되어 있다는 에러이다. 즉, 같은 함수가 중복되어 정의되어 있다는 것이다.


샘플 코드를 보고 무엇이 문제인지 생각해보자.

 

Transform.h

#include "Rotation.h"

class Transform
{
public:
	Rotation rotation;
};

 

Rotation.h

class Rotation
{
public:
	static float Angle(const Rotation& r1, const Rotation& r2);
};

float Rotation::Angle(const Rotation& r1, const Rotation& r2)
{
	return 0.0f;
}

 

main.cpp

#include <iostream>
#include "Transform.h"

int main()
{
	Transform a;
	Transform b;
	Rotation r;
	auto angle = r.Angle(a.rotation, b.rotation);

	std::cout << angle << std::endl;

	return 0;
}

 

언뜻 보기에는 문제가 없어 보이지만, 컴파일하면 LNK2005에러가 나타난다.

 

위 에러는 Transform.obj에서 나타났는데, main.obj에 이미 컴파일 된 Angle 함수가 정의되어 있기 때문이다. Transform.obj에서 Angle이라는 메서드를 만들었는데, main.obj에서 다시 만들려고 해서 나타난 에러이다.

 

해결 방법은 정말 간단하다.

단순히 중복되어 있는 함수를 inline화 시키면 된다.

inline float Rotation::Angle(const Rotation& r1, const Rotation& r2)
{
	return 0.0f;
}

 

inline화를 함으로써 컴파일러가 동일한 함수가 중복 정의되더라도 이를 하나의 정의로 취급한다.

Angle 함수에 inline을 붙이면 정상적으로 컴파일 및 실행이 된다.

 


위 코드에 대한 문제해결에서 다음을 알 수 있다.

클래스 외부에서 함수의 body를 정의할 때는 inline을 명시적으로 추가하지 않는 이상, 암묵적으로 inline으로 간주되지 않는다.

 

Note: class 내부의 함수는 암묵적으로 inline 함수로 간주된다.

Note2: static이든 단순 멤버 함수든 클래스 외부에서 body를 정의하면 inline화 되지 않는다.

 

전체 프로그램 단위에서 Angle이 단 한번만 정의되고 사용된다면 상관없지만, 위와 같이 여러 파일에서 참조할 경우, inline 함수가 아니면, 각 번역 단위에서 복사본이 생성이된다. 따라서 같은 정의를 가진 함수가 생겨났고, 이를 호출 할 때, 어떤 함수를 호출할지 결정하지 못하므로, LNK2005 에러가 나타나게 된다.

 

(내 생각이긴 한데, 인라인 함수는 말 그대로, 함수 대신 가져다 쓰는 치환느낌이니까, 해당 메서드를 치환하여 그 자리에 코드를 넣는다고 한다면 상관없을 것이다. 그러나, inline을 붙이지 않는 함수가 헤더에 정의되어 있으면, 이 헤더가 포함된 파일들을 컴파일하여 오브젝트 파일을 생성하면, 각 오브젝트 파일에 이 함수가 각각 따로따로 정의되어 있을 것이다.)

 

중복 정의를 피하기 위해, 헤더에 정의된 클래스 외부 함수에 대해서는 명시적으로 inline을 붙여주자.

'Language > C++' 카테고리의 다른 글

Factory 패턴 (팩토리 패턴)  (0) 2024.11.28
브릿지 패턴 (Bridge Pattern) + Pimpl  (0) 2024.11.26
템플릿 특수화, constexpr if 그리고 concept  (3) 2024.10.16
[C++20] concepts - requires  (0) 2024.10.02
Singleton 패턴  (0) 2024.09.26