[C++] class A; 의 역할이 궁금합니다.

vudghkzm의 이미지

A.h 에는 A 라는 클래스의 definition 코드가 있고, A.cpp 에는 A 클래스의 implementation 코드가 있습니다.

그리고 B.h 에는 다음과 같이 구성되어 있습니다.

#include "A.h"
 
class A;
 
class B {
    ...
}

A.h 를 인클루드 했기 때문에 클래스 A 를 참조할 수 있을텐데, 여기서 class A; 문장을 왜 썼는지가 궁금합니다.

익명사용자의 이미지

타입이 선언되어 있지 않아서 그렇습니다.
아마 그럴겁니다. -.-;;
만약 class A가 B의 멤버로 속하지 않으면 저렇게 쓰지 않아도 됩니다.
그러나 A가 B에 속한다면 class A;라고 해서 미리 형태를 선언해야 합니다.
왜냐구요? 그걸 모르니 ㅠ_ㅠ;

흠. 여튼 만약에 class B { void write(); }
void B::write() { A a;
a.어쩌구();
} 이렇게 쓸 경우에는 class A해서 프로토 타입 선언 안해줘도 됩니다. -.-;
에구 핵심은 쏙 빠졌군요;

익명사용자의 이미지

class A; 이거 필요 없는 부분이죠.

아마 처음에는 #include "A.h" 이 부분이

B.cpp 에 있었을 겁니다. 지금처럼 B.h 가 아니구요.

그랬다가 무슨 이유에서인지 지금처럼 바뀐걸로 보이는군요.

ps. #include 는 cpp 파일에만 쓰는게 여러모로 좋더라구요.

ssehoony의 이미지

#include를 헤더에 넣을 건지 소스에 넣을건지 고민을 많이 해봤는데요.

제 경우 결론은 "include 는 헤더에 넣는게 좋다"였습니다.
이유는, a.h 를 include 해서 사용하려 하는데 a.h를 사용하기위해 b.h, c.h, d.h 를 include 하길 요구한다면, a.h 를 다른 곳에서 사용할 때는 a.h 이전에 b.h, c.h, d.h 를 include 를 해줘야 합니다. 이거 귀찮더군요.
하지만 b.h, c.h, d.h 를 include 하는 코드를 a.h 에 넣어 두면 그냥 a.h 만 include 해서 사용하면 됩니다.
근데, 이 결론이 왠지 찜찜한 것은 리눅스의 기본 함수들을 보면 해당 관련 함수 하나만 include 하면 안되고 다른 부가 헤더들도 include 하도록 되어 있습니다.
예를 들어 man select 를 해서 select 를 사용하기 위해 include 해야하는 것들을 보면

       /* According to POSIX 1003.1-2001 */
       #include <sys/select.h>
 
       /* According to earlier standards */
       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

이렇게 되어 있죠.
이걸 보면 익명님 말씀 처럼 .c/.cpp 에 include 를 하는게 좋기 때문에 이런 규칙을 사용하는게 아닐까 하는 생각도 듭니다.

이에 대한 해답이 있나요?

익명사용자의 이미지

정답이 있다고 생각지는 않지만

cpp 에서 #include 하는것이 컴파일 시간이 많이 줄어듭니다.

보통 <> 괄호 사용하는 시스템헤더(?) 들은

수정이 안 되기 때문에 .h 에서 #include 할때가 많습니다.

다만 사용자가 새로 만든 클래스의 #include 는 꼭 cpp 에서 해주는 버릇이 있습니다.

그리고,

멤버로 가질때는 포인터 형태로 많이 씁니다.

class A;

class B
{
A* m_a; // 포인터 형태라 #include 필요없음
}

다음처럼은 잘 하지 않습니다.

#include "A.h"

class B
{
A m_a;
}

doldori의 이미지

#include를 헤더에서 할 것이냐 소스에서 할 것이냐에 대한 정답은 없습니다.
대원칙은
(1) 번역이 #include 순서에 영향을 받으면 안된다.
(2) 파일간 종속성은 최소한으로 줄이는 것이 좋다.

(2)를 고려하면 아무래도 소스 쪽에서 하는 경향이 많아지겠지만,
inline 함수를 쓰면 헤더에서 해야 할 경우도 생기게 되지요.
(2)를 위해 pimpl idiom이니 compilation firewall이니 하는 기법들이 나오는데,
그것을 맹목적으로 적용하는 것이 바람직하지만은 않습니다. 적절히 취사선택해야죠.
프로그래밍은 의사결정의 연속이라는 말도 있잖습니까.

SoftOn의 이미지

아래와 같이 짜면 안되지만 아래와 같은 경우에 필요합니다.

a.h

#include "b.h"
class B;
class A {
  ...
  B b1;
}

b.h

#include "a.h"
class A;
class B {
 ...
 A a1;
}
falaris의 이미지

헉..여태까지 저는 header파일은 대부분 header에서 인클루드 하여서 사용 하였는데,
cpp에서 헤더파일을 불러 오는것이 얼마나 컴파일 시간이 줄어 드는지 궁금합니다.!!

--------------@@
젠투교+emacs교로 서서히 가는중!~@

파피루스의 이미지

c/cpp 컴파일러는 ".cpp" 혹은 ".c" 파일 단위로 컴파일하며, include 문장은 단순히
텍스트 확장에 지나지 않습니다(절대 복잡한 과정이 아니며, "include" 내용을 cpp 파일에 복사해서
붙이는 수준입니다.)

결론은 ".cpp" 혹은 ".c" 파일을 컴파일하는데, 컴파일하기 위한 정보를 제공하기 위해, 공통적으로 여러군데서
쓰일수 있는 정보를 보통 헤더파일에 기입하게 되지요.

그 공통된 정보가 클래스인경우 보통 클래스 자체에 대한 모든 정보를 기입하게 됩니다. 멤버 변수 타입, 멤버 함수 타입등이지요.
이러한 정보는 클래스 변수 정의를 할때 쓰입니다.

하지만 클래스에 대한 포인터 변수 혹은 레퍼런스 변수를 정의한다면, 사실 클래스에 대한 모든 정보는 필요없고,
"이토큰은 클래스 타입명 이다" 라는 정보만 필요합니다.

즉, "class A;" 라는 문장은 "A라는 토큰이 클래스이다" 라는 정보를 컴파일러에게 줍니다.

이 정보는 "A* pA;" 라는 문장을 만났을때 컴파일러가 "undefined symbol" 등과 같은 에러를 출력해야 하는지 말아야 하는지 결정하게 되죠.

즉, "A* pA;" 라는 문장을 컴파일하기 위해서는 "A 라는 키워드가 클래스 이다" 라는 정도의 정보만 있으면 되는거죠.

그와는 다르게 "A objA;" 라는 문장의 경우 컴파일러가 컴파일할때, 최소한 "클래스 A가 몇바이트 차지하는가?" 라는 정보라도 있어야,
스택혹은 데이터세그먼트를 적절히 잡을수 있는 코드를 생성할수가 있는거죠.

도움이 되었으면 좋겠네요.

댓글 달기

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