class에 대한 include 에 대한 문의

killereco의 이미지

아래와 같은 소스가 있습니다.

A.h
--------
class C
 
class A {
 C m_c;
};
 
A.cpp
------------
#include "C.h"

위의 코드 처럼 "C"라는 클래스를 쓰는데. header 파일에서 include 하지 않고 .cpp 파일에서 include 하는 이유가 궁금합니다.

그것이 일반적인 프로그래밍 경향인가요?

chadr의 이미지

C/C++이 소스와 헤더가 분리된 방식의 언어라서 그럽니다.

특정 클래스와 함수를 사용하기 위해서는 헤더파일을 인클루드하는데 헤더에서 이것저것들을 인클루드하면
잘못하다간 꼬이게 됩니다.. 또한 불필요한 인클루드가 많아져 컴파일 타임을 증가시키는 원인이 되기도 합니다.

그래서 가능하면 소스에서 헤더파일을 인클루드 하시는걸 추천합니다.

단.. 어떤 클래스에서 다른 클래스의 인스턴스를 사용하는 코드가 있을때는 불가피하게 헤더에서 다른 헤더를
인클루드 하게 되는데 이때는 별 방법이 없는것 같습니다.

ps. 그런의미에서 헤더와 소스가 분리 되어있지 않은 java나 c#같은 언어가 참으로 예뻐보입니다;
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

ssehoony의 이미지

의존성을 최대한 줄이기 위해섭니다.

a.cpp 말고 만약 b.cpp 에서도 a.h 를 include 한다고 할때
b.cpp 는 C 클래스를 직접 사용하지 않는다면 b.cpp 는 C 클래스에 대해 알 필요가 없습니다.
하지만 a.h 에 c.h 를 include 를 했다면 b.cpp 는 c.h 도 include 하게 되므로서
b.cpp 를 컴파일할때 불필요하게 c.h 도 컴파일 해야 하는 단점이 있습니다.
만약 c.h 가 굉장히 복잡한 헤더라면 컴파일 시간이 꽤 늘어나겠죠.
이런건 피하겠다는 생각하에서 저런식으로 구조가 나오게 되는데

제 개인적인 취향은 그냥 a.h 에 c.h 를 include 합니다.
뭐 컴파일 조금 더 걸리면 어떻습니다. 요즘 컴터 빠른데. ^^ ㅎㅎ
게다라 요즘은 pre-compile-header 라는 기술도 있어서 이거 사용하면 그리 크게 문제 되지도 않습니다.
이쪽은 딱히 정답이라는게 없으니깐 그냥 이렇게도 해보고 저렇게도 해본후
본인의 입맛에 맞는것을 선택하시면 좋을 듯 합니다.

philnet의 이미지

프로젝트 규모가 커질 때(소스 파일 개수가 몇 백개, 1000개 이렇게 되면) 컴파일 시간이 꽤 걸릴 수 있습니다.
여러 명이 나눠서 작업할 경우, 성질 나쁜(?) 다른 사람한테 욕을 먹을 수도 있구요.

아시는 분들은 다 알고 계시겠지만 아직 잘 모르시는 분을 위해 부가 설명 드리면,

한 클래스가 포인터나 레퍼런스 타입의 멤버 변수로 다른 클래스에 포함될 경우에는 전방 선언으로도 충분합니다. 또 멤버 함수의 인자나 반환 타입으로 사용될 경우도 전방 선언으로 충분하구요.

아래의 예에서 E.h 에는 "B.h", "C.h", "D.h" 가 #include 될 필요가 없습니다. B, C, D의 (전방) 선언만으로 충분하기 때문입니다. 이에 비해 A는 객체 타입의 멤버 변수로 사용되기 때문에 반드시 정의되어야 하므로 #include 되어야 하고요.

#include "A.h"
class B;
class C;
class D;
 
class E
{
public:
  E(A a);
  E(B* b);
  E(C& c);
  D Fnc(D d);
  A m_a;
  B& m_b;
  C* m_c;
};

이펙티브 C++ 책에서 이걸 보았을 때 꽤 놀랐던 기억이 아직도 생생하고요, 그 이후 되도록이면 타입의 멤버 변수 사용하는 것 대신, 포인터나 레퍼런스로 사용하고 있고, 대부분 문제 없이 사용할 수 있습니다.

포인터 멤버 변수를 쓸 때에는 경우에 따라 복사 생성자나 할당 연산자를 제공해야 하는 부담이 생기지만, 이건 또 스마트 포인터(boost::shared_ptr 같은)을 사용해서 처리합니다.
--------------------
* (오타가 있었군요. -_-) D.h -> E.h로 수정합니다.

winner의 이미지

header file 은 #ifndef #endif 를 써서 추가적인 include 를 하지 못하게 하는 것 아닙니까?

추가적인 include 는 compile time 의 문제이전에 중복정의의 문제가 발생할 거구요..

C++ 에서 header file 의 속성으로 인하여 compile time 에 영향을 크게 주는 것은
template 정도일텐데요.

ssehoony의 이미지

a.h 안에서 c.h 에 있는 클래스의 내부 함수를 콜하거나 멤버변수를 접근하는 코드등이 있다면
a.h 에서는 꼭 c.h 를 include 해야 합니다.
하지만 a.h 에서 c.h 에 있는 것을 직접적으로 사용하지 않고 그냥 클래스의 존재 여부만
알아도 충분하고 경우는 c.h 를 include 하는 대신 a.h 에서 c.h 에 있는 내용중 필요한 것만
전방선언것으로 컴파일 하는데는 충분합니다.

그리고 말씀하신것 처럼 템플릿의 경우는 컴파일 시간에 영향을 굉장히 크게 주고, 일반 .h 의 경우는 영향은 있지만 크지는 않습니다. 하지만 MFC 같이 굉장히 거대한 라이브러리의 경우는 .h 의 파일만
수십~수백에 달하기 때문에 그 영향력을 무시 할 수 없는 경우가 있긴합니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.