본문 바로가기

C/C++

[Google C++ Style Guide] 1. Header Files

http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml

 

위의 내용을 제 나름대로 번역한 겁니다.

물론 오역 굉장히 많습니다 --;

 

C++ 프로그래밍 적인 면에서 스콧 마이어스의 Effective C++에서 보던 내용이 많고,

스타일은 리눅스 계열의 스타일인것 같아 제가 당장 쓰기 어려운 것도 많습니다.

그런것은 제 나름대로 사용하면 될 것 같고,

문서에도 나와있지만, 정답이 없는 코딩 스타일의 경우는 일관성이 가장 중요해 보입니다.

 

긴 내용이라 챕터별로 올립니다. (전문은 파일 첨부)


Google C Style Guide.docx



 

Google C++ Style Guide

 

1. Header Files            

단위 테스트와 main()함수만 있는 .cpp파일을 제외하고 일반적으로 모든 .cpp파일은 .h파일과 쌍으로 연결되어 있다.

헤더 파일의 올바른 사용은 여러분의 코드의 가독성과크기 그리고 성능향상에 큰 차이점을 만들 수가 있다.

 

 

A.     The #define Guard (#define 보호)

모든 헤더 파일은 다중 포함을 방지하기 위해 #define 가드를 가진다.
<PROJECT>_<PATH>_<FILE>_H_
 의 포맷을 사용한다.

 

심벌명의 유일성을 보장하기 위해서 프로젝트 소스 트리의 완전 경로에 기반 해야 한다.
예를 들어 foo 라는 프로젝트에 foo/src/bar/baz.h 파일인 경우 아래처럼 할 수 있다.

 

#ifndef FOO_BAR_BAZ_H_

#define FOO_BAR_BAZ_H_

 

...

 

#endif  // FOO_BAR_BAZ_H_

 

 

B.      Header File Dependencies (헤더 파일 의존성)

전방 선언(forward declaration)으로 충분하다면 #include를 사용하지 않는다.

 

.h파일에 #include 를 이용하여 다른 .h파일을 포함시키면 그 파일이 변경될 때마다 코드를 다시 컴파일 해야 한다그래서 inlclude를 최소화 하는 것이 좋다.

 

전방선언을 사용하여 include를 최소화 할 수 있다. 예를 들어헤더파일이 File 클래스를 사용하는데 File클래스의 선언에 접근하지 않는다면  #include "file/base/file.h" 대신에  class File; 를 사용할 수 있다.

 

헤더파일에서 클래스 정의에 접근하지 않고 클래스 Foo를 사용하는 방법은 다음과 같다.

 

-       Foo* 또는 Foo& 즉 클래스 포인터나 참조자를 선언한다.

-       Foo 타입의 리턴 값이나 인자를 가진 함수를 선언(정의가 아닌)한다.

-       Foo 타입의 static 데이터 멤버를 선언한다. static데이터 멤버는 클래스 정의 밖에서 정의 되어지기 때문이다.

 

 한편 클래스가 Foo의 서브클래스이거나 Foo타입의 데이터 멤버를 갖는다면 Foo에 대한 헤더파일을 #include 해야 한다.


때때로 객체멤버 대신 포인터멤버(scoped_ptr를 사용하면 더 좋다)를 이용하는 것이 더 좋다그러나 이것은 코드 가독성을 복잡하게 하고 성능비용을 지불 해야 한다그래서 헤더파일에 인클루드하는 것을 최소화하기 위한 것이 유일한 목적이면 이런 변환은 피한다.

 

 

C.      inline Functions (인라인 함수)

10라인 이하의 아주 작은 함수일 때만 인라인 함수를 정의한다.

 

정의 : 

보통의 함수 호출 메카니즘을 통한 함수 호출 보다 컴파일러가 함수를 인라인으로 선언 할 수 있다.


장점 :

인라인된 함수는 인라인된 함수가 작은 한 더 효과적인 오브젝트 코드를 생성할 수 있다.

 

단점 :

인라인의 과도 사용은 프로그램을 더 느리게 만들 수 있다. 
인라인 함수의 사이즈에 따라 코드 크기를 크게 하거나 작게 만들어 질 수 있다.
매우 작은 함수를 인라인하는 것은 보통 코드 크기를 감소시킬 수 있지만 매우 큰 함수를 인라인하는 것은 코드 크기를 극적으로 크게 만든다요즘 프로세서에서 더 작은 코드는 더 나은 인스트럭션 캐시(instruction cache)를 사용하기 때문에 보통 더 빠르게 실행된다.

 

결론 :

A decent rule of thumb (경험상) 10라인 이상인 함수는 인라인하지 않는 것이 좋다그리고 loop switch 문장이 들어간 함수는 인라인은 효과적이지 않다그리고 가상 또는 재귀함수는 일반적으로 인라인되지 않으며보통 재귀 함수는 인라인으로 사용하면 안된다.

 

 

D.     The –inl.h Files (inl.h 파일)

당신은 복잡한 인라인 함수들을 정의할 필요가 있을때 파일명뒤에 -inl.h 를 사용한다.

 

 

E.      Function Parameter Ordering (함수 파라미터 순서)

함수를 정의할때 파라미터 순서는 입력 -> 출력 순으로 한다.


C/C++ 
함수들의 파라미터들은 입력만 있는 경우출력만 있는 경우 그리고 둘 다 있는 경우가 있다.
입력 파라미터들을 보통 값 또는 const 참조자들인 반면출력 그리고 입/출력 파라미터들은 non-const 포인터일 것이다. 함수 정의 시 파라미터 순서는 출력 파라미터 앞에 모든 입력 파라미터를 놓아라.

이것은 엄한 규칙(hard-and-fast rule)이 아니다.  출력과 입력 둘 다 있는 파라미터(클래스나 구조체)들은 아마도 연관된 함수의 일관성을 따라 위 규칙을 알맞게 바꿀(bend the rule) 필요가 있을 것이다.

 

 

F.      Names and Order of Includes (include 이름과 순서)

숨겨진 의존성을 피하고 가독성을 위하여  다음의 순서대로 include 한다.

라이브러리, C++라이브러리기타 다른 라이브러리프로젝트 헤더 파일 (.h)

 

프로젝트의 모든 헤더파일들은 UNIX 디렉토리 쇼트컷(shortcuts : (. : 현재 디렉토리 ) 또는 ( .. : 부모 디렉토리 ) ) 사용없이 프로젝트 소스 디렉토리 구조로 인클루드 한다.


예를 들어 google-awesome-project/src/base/logging.h 

#include "base/logging.h" 처럼 인클루드 한다. ( ./ or ../ 를 사용하지 말라는 것)


 dir/foo.c
의 주 목적이 dir2/foo2.h 의 기능을 구현하거나 테스트하기 위한 경우 아래처럼 인클루드 순서를 정해라.

 

1. dir2/foo2.h (preferred location  see details below). 
2. C system files.
 
3. C++ system files.
 
4. Other libraries' .h files.
 
5. Your project's .h files.

 

이 순서대로 하면 숨겨진 의존성들을 줄일 수 있다모든 헤더 파일은 스스로 컴파일 되어야 하는데, hello.cpp에서 처음 include 되는 헤더 파일을 hello.h로 한다는 의미이다.

그리고 각각의 섹션 내에서는 알파벳 순으로 #include 하는 것이 좋다.


예를들어 google-awesome-project/src/foo/internal/fooserver.cc 는 아래처럼 #include 될 것이다.

 

#include "foo/public/fooserver.h"  // Preferred location.

 

#include <sys/types.h>

#include <unistd.h>

 

#include <hash_map>

#include <vector>

 

#include "base/basictypes.h"

#include "base/commandlineflags.h"

#include "foo/public/bar.h "