클래스 관련해서 명확히 짚고 넘어가야하는데 선언과 정의인데,
int f(int a, int b); 요렇게 쓰면 선언이야. 인자 2개(int형 a와 int형 b)를 받고 int를 반환하는 함수 f가 있다는걸 컴파일러에게 알려주는 것.
int f(int a, int b)
{
return a + b;
}
요건 함수 정의야. a와 b를 받아서 반환하라는 함수가 되는거지.
마찬가지로 멤버 함수를 선언할 때,
class myclass
{
int f(int, int);
};
요건 함수 선언. myclass의 멤버 함수 f가 있는데, 이 멤버 함수는 인자 2개(int, int)를 받고 int를 반환한다는 걸 컴파일러에게 알려주는거야.
int myclass::f(int a, int b)
{
return a + b;
}
이건 멤버 함수 정의.
근데 멤버 함수는 선언부에 다음처럼 정의를 같이 넣을 수 있어.
class myclass
{
int f(int a, int b) { return a + b; }
};
예를 들어서 같이 보면,
https://paiza.io/projects/bJeGE1vrTl9fsoz0ADfgnw
위의 예는 멤버 함수 선언과 정의를 분리해놓은 형태야. 근데 myclass.hpp를 배포하려면 myclass.cpp를 같이 배포해야하잖아? 그럼 쓰는 입장에서 myclass.cpp를 별도로 컴파일해야하니까 좀 많이 귀찮아. 그니까 header-only 라이브러리를 만들기 위해 멤버 함수 정의를 hpp 파일에 넣으면,
https://paiza.io/projects/9e-oweLs_adu8pDZ3pcKbg 가 되는데, 보다시피 이건 링크 에러가 발생해.
이건 뭐냐면, 함수 정의는 하나만 있어야하는데, myclass::print() 함수가 main.cpp에도 있고, b.cpp에도 있기 때문에 multiple definition 링크 에러가 발생하는거야.
함수 정의를 헤더에 넣으려면 '함수의 정의가 하나다'라는 걸 충족시켜줘야하는데, 이를 위해 inline 키워드를 넣으면 다음과 같이 잘 돌아가.
https://paiza.io/projects/tqsrAALUiwor0TiiuSwkkw
inline 함수는 실제 인라이닝이 되는가의 여부와는 별개로, ELF 포맷이라면 weak 속성을, VC++이라면 selectany 던가 하는 속성이 붙은 심볼이 생성되는데, 이건 뭐냐면 링커에게 '함수 정의가 여러개 발견되면 그 중에 하나만 갖다 써라'라고 알려주는거야.
근데 또 이러면 멤버 함수마다 정의부를 다 따로 써줘야하니까 귀찮잖아? 그럼 그냥 위에서 설명한것처럼 멤버 함수 선언부에 정의를 같이 써도 돼.
https://paiza.io/projects/zPz-K6EAvRK2GxlJ_hZdlA
그니까 ㅇㅇ가 말한 '헤더 파일을 따로 못만든다'라는건 완전 개소리고, '함수 정의가 길어질 경우에 헤더 파일만 보고서 인터페이스를 파악하기 어려워진다'는 소리는 맞아. 근데 라이브러리가 일정 규모 이상이 되면 어차피 문서화를 해야하고, 그럼 어차피 doxygen이든 뭐든 주석 떡칠이 들어가기 때문에 헤더파일은 읽기 어려워져. 그러니까 취향에 따라 '헤더만 보고도 알 수 있게 선언과 정의를 분리한다'나, '어차피 문서화할거니까 선언에 정의도 같이 넣는다'라던가 선택하면 된다.
오 paiza.io라는게 있네 개꿀팁 ㄱㅅ
https://en.wikipedia.org/wiki/Class_implementation_file
소스파일 여러개 쓸 수 있는거 찾다보니까 방금 찾은건데 꽤 쓸만한 것 같아 ㅋㅋ
뭘 열심히 설명하려고 노력은 하고 있으나 C도 헤더파일 따로 안만들고 #include\<foo.c\>해도 되는데 그걸 헤더파일을 만들었다 하지 않지 ㅋ
아 이 새키는 그냥 알려는 생각이 없는거였구나 시간만 버렸네
모르는걸 알려줘야 알지 임마 ㅋ
시간버리는 좋은 예
그래도 다른사람들이 유익한시간을 갖게되니 시간버린것만은 아니라생각하셈ㅋㅋ