#include 문의 위치, class 선언 위치

jatin의 이미지

너무 당연한 질문인줄로 알고 있습니다만..
C#만 하다가 C++로 전향한 개발자인지라 질문드립니다.

질문1:
C++ 소스파일은 흔히 [name.cpp] 와 [name.h] 로 구분됩니다.
이 두 개의 파일 중에서 #include문이 들어가야하는 관례적인 위치가 궁금합니다.
[*.cpp] 일까요 아니면 [*.h]일까요?

질문2:
아래와 같이 #include문을 작성하였습니다.

#include "cname.h"

빌드도 잘 됩니다.
그런데 ( class CName; )과 같이, 소스파일 상단에
class 선언을 하는 코드를 본적이 있습니다.
이는 class를 명시적으로 사용하겠다고 해석하는 것이 맞나요?

답변 부탁드립니다.

cppig1995의 이미지

질문 1과 2는 이어지는 질문인데요, 질문 1의 경우 자신의 관습에 따르면 될 것 같습니다.

만약 헤더 파일 A.h가

class A
{
B b;
};

일 때 A.h에서 B.h를 #include하지 않고 A.cpp에서 #include하려면
A.h 상단에 class B;를 넣어야겠지요.

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

지리즈의 이미지

해당 해더가 그 include를 필요로 하는가 아닌가로 결정하면 됩니다.

이를테면, header(a.h)내에서 b.h의 내용을 참조한다면 반드시 a.h에 b.h를 include해야겠지요.
(위의 참조란 b.h를 include하지 않고서는 a.h가 컴파일 오류를 낸다는 뜻입니다.)
하지만, a.h에 다른 헤더파일을 참조할 필요가 없다면, 우선적으로는 a.cpp에 넣는 것이 바람직합니다.

예를 들어,
a.cpp이 b.h를 필요로 할 때, 이를 a.h에서 b.h를 include하면,
b.h를 필요로 하지 않는 c.cpp에서 a.h를 불러올경우 불필요한 b.h를 include하게 됩니다.

이는 디버그할 때 골치아픈 문제에 처할 수 있지요.

이에 확장에서 a.h에 선언할 것인가 혹은 a.cpp에 선언할 것인가 하는 문제도
같은 맹락으로 이해해서 적용하면 됩니다.

특정 함수나 클래스, define, 혹은 전역변수가 a.cpp에만 필요하다면,
이 역시 a.h에서 선언하는 것이 아니라 a.cpp의 상단에 선언하는 것이 옳죠.

즉, 헤더란 다른 cpp과 링크될때 공유할 필요가 있는 내용을 담는 것이 목적이라고 보시면 됩니다.
따라서, 가급적 헤더는 꼭 공유할 필요성이 있는 간결하고 필수 불가결한 내용만 포함하는 습관을 들이는 것이
덩치가 커다란 소프트웨어를 개발할 때 큰 도움이 됩니다.

따라서, 공유할 내용이 없이 오직 외부만 참조하는 cpp 파일 같은 경우 헤더 없이 작성하기도 합니다.

There is no spoon. Neo from the Matrix 1999.

There is no spoon. Neo from the Matrix 1999.

lugi의 이미지

경험상 header안에 header는 가능한 피하고 있습니다.

다만, 특정 header A 에서 다른 header B를 필요하는 경우, 이에 대해서 주석으로만 명시하여 놓고 cpp파일에서 header A를 include하기 전에 먼저 header B를 include해 줍니다. 이는 header에 header를 넣다보면 나중에 header간의 관계가 추적 불가능할 정도로 복잡해지는 경우가 종종 생기기 때문입니다.

//This is A.cpp
#include B.h
#include A.h
 
...

또한 모든 header의 시작과 끝에 아래와 같이 매크로를 사용하여 header가 한 파일에서 두번 이상 include되었을때를 대비합니다.

#ifndef _XXXX_H_ 
#define _XXXX_H_
 
...
 
#endif //_XXXX_H_

--------------------------------------------------------------------------------------
조금씩이라도 전진한다.

jick의 이미지

뭐 제 경험일 뿐이지만, header A에서 B를 필요로 한다면 넣는 것을 강력히 선호합니다. 그렇지 않고 "A를 사용하려면 반드시 B를 먼저 include하시오!" 했을 경우 사람들이 include 하나 추가할 때마다 주석을 다 읽고 한다는 보장도 없고, 멀쩡한 .c(c) 파일이 include 문 순서를 바꾸면 되다가 말다가 하는 사태가 벌어집니다.

그리고 이러면 필연적으로 사람들이 귀찮게 에러 나는 사태를 피하기 위해 "필요할 것 같은 header는 죄다 include"해 버리게 됩니다. include를 굳이 나눠놓은 본래 목적을 위반할 뿐더러 컴파일 속도도 느려지고 dependency가 다 엉키죠. 좀 더 심한 케이스에선 누군가 "에잇 나는 항상 a b c d e를 필요로 하는데 왜 이걸 다 나눠놓은 거야!"라고 mymodule_common.h 같은 파일을 만들게 됩니다. (물론 이 파일에는 include문이 추가되면 됐지 결코 줄어드는 법은 없습니다.) 그러면 이제 dependency는 안드로메다로...

가장 최악의 사태는, a.h에서 b.h의 class X를 필요로 하는데 누군가 실수로 c.h를 만들고 또다른 class X를 선언한 다음 제 3자가 c.h와 a.h를 차례로 (하지만 b.h는 빼고) include하면서 발생합니다. 왜 에러가 나는지 찾는데 하세월...

swirlpotato의 이미지

헤더에 헤더를 첨부하다보면 흔히 말하는 "코드가 떡이 된다" 라는게 되더군요

글 도배 해보세... 룰루랄라

jatin의 이미지

우문현답이군요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.