Coding Memo
[LNK2005] already defined in ~~.obj / inline 함수 본문
먼저, 이 포스팅을 작성하게된 이유는 헤더 파일에 있는 함수들은 모두 암묵적으로 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 |