클래스 코드를 헤더와 cpp 파일로 분리


169

간단한 클래스의 구현 및 선언 코드를 새로운 헤더 및 cpp 파일로 분리하는 방법에 대해 혼란스러워합니다. 예를 들어 다음 클래스의 코드를 어떻게 분리합니까?

class A2DD
{
  private:
  int gx;
  int gy;

  public:
  A2DD(int x,int y)
  {
    gx = x;
    gy = y;
  }

  int getSum()
  {
    return gx + gy;
  }
};

12
몇 개의 주석 만 : 생성자는 본문에 멤버를 설정하는 대신 항상 초기화 목록을 사용해야합니다. 좋은 간단한 설명은 다음을 참조하십시오 codeguru.com/forum/showthread.php?t=464084 그것은 적어도 대부분의 장소에서, 관습은 상단에있는 공공 필드를 가지고, 또한. 아무런 영향을 미치지 않지만 공개 필드는 클래스의 문서이므로 맨 위에 표시하는 것이 좋습니다.
martiert

2
@martiert 사용자가이 조언에 따라 public:멤버를 옮겼지만 멤버들 사이에 의존성이 있지만 멤버가 선언 순서대로 초기화되었다는 것을 아직 알지 못했다면 맨 위에 멤버가 있으면 많은 영향을 줄 있습니다. ;-)
underscore_d

1
@underscore_d 맞습니다. 그러나 다시, 우리는 모두 경고로 오류를 컴파일하고 생각할 수있는 모든 경고를 컴파일하고 있습니다. 그것은 적어도 당신이 이것을
망치고 있다고 말하지만

@martiert 좋은 점, 경고를 생성하는 것을 잊어 버렸습니다-대부분 경고 만 읽은 경우 :-) 경고를 사용하고 모두 코딩하려고합니다. 피할 수없는 몇 가지가 있으므로 '경고 해 주셔서 감사합니다.하지만 제가 무엇을하고 있는지 알고 있습니다!' -그러나 나중에 혼동을 피하기 위해 대부분 수정하는 것이 가장 좋습니다.
underscore_d

공공 장소를 맨 위에 두는 것은 스타일 일뿐입니다. 너무 많은 사람들이 불행히도 제 의견으로는 채택했습니다. 또한 @martiert가 언급했듯이 몇 가지 사항을 명심해야합니다.
Vassilis

답변:


232

클래스 선언은 헤더 파일에 들어갑니다. #ifndef포함 가드 를 추가 하거나 MS 플랫폼에있는 경우 사용할 수도 있습니다 #pragma once. 또한 개인을 생략했습니다. 기본적으로 C ++ 클래스 멤버는 개인입니다.

// A2DD.h
#ifndef A2DD_H
#define A2DD_H

class A2DD
{
  int gx;
  int gy;

public:
  A2DD(int x,int y);
  int getSum();

};

#endif

구현은 CPP 파일로갑니다.

// A2DD.cpp
#include "A2DD.h"

A2DD::A2DD(int x,int y)
{
  gx = x;
  gy = y;
}

int A2DD::getSum()
{
  return gx + gy;
}

53
템플릿 프로그래밍을 수행하는 경우 컴파일러가 컴파일 할 때 올바른 코드를 인스턴스화 할 수 있도록 모든 것을 .h 파일에 보관해야합니다.
linello

2
당신이해야합니까 #ifndef헤더에 물건을?
Ferenc Deak

4
따라서 이것은 헤더 파일을 포함하는 모든 파일이 개인 구성원을 "볼"것임을 의미합니다. 예를 들어 lib와 해당 헤더를 게시하려면 클래스의 개인 멤버를 표시해야합니까?
Gauthier

1
아니요, 훌륭한 개인 구현 관용구가 있습니다. en.wikipedia.org/wiki/Opaque_pointer 이를 사용하여 구현 세부 사항을 숨길 수 있습니다.
Ferenc Deak

3
"클래스 선언은 헤더 파일에 들어갑니다"라는 문구가있는 작은 nitpick 이것은 실제로 선언이지만 정의이기도하지만 후자가 전자를 포함하기 때문에 클래스 정의가 헤더 파일로 이동한다고 말하고 싶습니다. 변환 단위에는 클래스의 정의가 아니라 멤버 함수의 정의가 있습니다. 동의합니다. 약간의 편집 가치가 있습니까?
lubgr

17

일반적으로 .h에는 모든 데이터와 모든 메소드 선언 인 클래스 정의가 포함됩니다. 귀하의 경우에 이와 같이 :

A2DD.h:

class A2DD
{
  private:
  int gx;
  int gy;

  public:
  A2DD(int x,int y);    
  int getSum();
};

그리고 .cpp에는 다음과 같은 메소드의 구현이 포함되어 있습니다.

A2DD.cpp:

A2DD::A2DD(int x,int y)
{
  gx = x;
  gy = y;
}

int A2DD::getSum()
{
  return gx + gy;
}

7

프로젝트를 파일로 분할하려는 경우 허용되는 답변 절차가 필요하지 않다는 주제를 더 광범위하게 연구 할 때이 질문에 걸려 넘어지는 독자들에게 지적하는 것이 중요합니다. 단일 클래스의 다중 구현이 필요한 경우에만 필요합니다. 클래스 당 구현이 하나 인 경우 각각에 대해 하나의 헤더 파일이면 충분합니다.

따라서 허용 된 답변의 예 에서이 부분 만 필요합니다.

#ifndef MYHEADER_H
#define MYHEADER_H

//Class goes here, full declaration AND implementation

#endif

#ifndef 등 전 처리기 정의를 통해 여러 번 사용할 수 있습니다.

추신. C / C ++가 'dumb'이라는 사실을 알게되면 주제가 더 명확 해지며 #include는 "이 시점에서이 텍스트를 덤프"하는 방법 일뿐입니다.


"split"파일을에 넣음으로써이 작업을 수행 할 수 있습니까? 아니면이 코드 구성 방법에 .cpp대해서만 .h"좋은"것입니까?
Benny Jobigan

1
일부 프로젝트는 헤더 및 (단일) 구현 파일을 분할하여 구현의 소스 코드를 공개하지 않고 헤더 파일을 쉽게 배포 할 수 있다고 생각했습니다.
칼 G

원래 C ++에서 배운 다음 몇 년 전에 C #으로 전환했으며 최근에 많은 C ++을 다시 수행했기 때문에이 점을 지적하게되어 기쁩니다. 파일을 분할하는 것이 지루하고 성가신 일이 무엇인지 잊어 버렸습니다. 나는 이것을 발견했을 때 그렇게하지 말아야 할 좋은 이유를 찾는 사람을 찾고있었습니다. @CarlG는 좋은 지적을 가지고 있지만 그 시나리오 외에는 모든 인라인 작업을 수행하는 것이 좋습니다.
피터 무어

6

기본적으로 함수 선언 / 정의의 수정 된 구문 :

a2dd.h

class A2DD
{
private:
  int gx;
  int gy;

public:
  A2DD(int x,int y);

  int getSum();
};

a2dd.cpp

A2DD::A2DD(int x,int y)
{
  gx = x;
  gy = y;
}

int A2DD::getSum()
{
  return gx + gy;
}

5

A2DD.h

class A2DD
{
  private:
  int gx;
  int gy;

  public:
  A2DD(int x,int y);

  int getSum();
};

A2DD.cpp

  A2DD::A2DD(int x,int y)
  {
    gx = x;
    gy = y;
  }

  int A2DD::getSum()
  {
    return gx + gy;
  }

아이디어는 모든 기능 서명과 멤버를 헤더 파일에 보관하는 것입니다.
이를 통해 다른 프로젝트 파일은 구현을 몰라도 클래스의 모습을 볼 수 있습니다.

그 외에도 헤더 대신 다른 헤더 파일을 구현에 포함시킬 수 있습니다. 헤더 파일에 포함 된 헤더가 헤더 파일을 포함하는 다른 파일에 포함 (상속)되므로 중요합니다.


4

헤더 파일에 선언을 남깁니다.

class A2DD
{
  private:
  int gx;
  int gy;

  public:
    A2DD(int x,int y); // leave the declarations here
    int getSum();
};

그리고 정의를 구현 파일에 넣습니다.

A2DD::A2DD(int x,int y) // prefix the definitions with the class name
{
  gx = x;
  gy = y;
}

int A2DD::getSum()
{
  return gx + gy;
}

둘을 섞어서 getSum() 예 : 헤더에 정의를 ). 이것은 컴파일러가 예를 들어 인라인에서 더 나은 기회를 제공하기 때문에 유용합니다. 그러나 구현을 변경하면 (헤더에 남아있는 경우) 헤더를 포함하는 다른 모든 파일의 재 구축이 트리거 될 수 있습니다.

템플릿의 경우 모든 템플릿을 헤더에 보관해야합니다.


1
헤더 파일에 개인 멤버 및 함수를 넣는 것은 구현 세부 정보 유출로 간주되지 않습니까?
Jason

1
@ 제이슨, 일종의. 이것들은 필요한 구현 세부 사항입니다. 예를 들어, 클래스에서 스택에서 소비하는 공간이 얼마나되는지 알아야합니다. 다른 컴파일 단위에는 함수 구현이 필요하지 않습니다.
Paul Draper

1

일반적으로 헤더 파일에는 선언과 실제로 짧은 인라인 함수 만 넣습니다.

예를 들어 :

class A {
 public:
  A(); // only declaration in the .h unless only a short initialization list is used.

  inline int GetA() const {
    return a_;
  }

  void DoSomethingCoplex(); // only declaration
  private:
   int a_;
 };

0

은 (예를 들어,이 헤더에이를 구현하도록 강요 템플릿 기능을 포함하지 않음) 일반적인 답변을 아주 간단 나는 너무 귀하의 예를 참조하지 않습니다, 제가 엄지 손가락의 규칙으로 따라하는 것은입니다 pimpl은 관용구

컴파일 시간이 빨라지고 구문 설탕이 많을 때 상당한 이점이 있습니다.

class->member 대신에 class.member

유일한 단점은 지불하는 추가 포인터입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.