2011-01-18 5 views
0

이것은 실제 질문이 아닐 수도 있습니다. 적절하지 않은 경우 이것을 닫으십시오.Java 방식으로 C++ 클래스를 정의하십시오.

C++에서

, 당신은이 a.ccb.cc으로 포함되어있어 예를 들어, 클래스가 두 번 정의되는, 하나의 소스 파일에 헤더와 구현을 혼합 할 수 없습니다 : 그런 다음

// foo.h 
#pragma once 
class Foo { 
    void bar() { ... } 
}; 

// a.cc 
#include "foo.h" 
class A {}; 

// b.cc 
#include "foo.h" 
class B {}; 

// Link all 
$ gcc -c -o a.o a.cc 
$ gcc -c -o b.o b.cc 
$ gcc -o main main.cc foo.o a.o b.o 

, 그것은 모호한 Foo :: bar() 세 개의 오브젝트 파일!

대신, 우리는 다른 파일에 구현을 분리해야합니다

// foo.h 
#pragma once 
class Foo { 
    void bar(); 
}; 

// foo.cc 
# include "foo.h" 
void Foo::bar() { ... } 

아마 큰 문제가 있지만, 일반적으로 a.ob.o에서 foo는 : 바()에 대한 바이너리가 동일하기 때문이다. 적어도 중복 된 선언이있는 것 아닌가요? 그리고이 중복에 의해 야기 된 몇 가지 혼란 :

  1. 선택적 매개 변수에 대한 기본값은 어디에 있습니까?

    class Foo { 
        void bar(int x = 100); 
    }; 
    

    또는

    void Foo::bar(int x = 100) { ... } 
    

    또는 두

    ?

  2. 인라인 간 이동 & 인라인 ... 아닌가요?

    인라인되지 않은 함수를 인라인 함수로 전환하려면 foo.cc에서 foo.h으로 코드를 이동하고 inline 키워드 접두어를 추가해야합니다. 그리고 아마도 2 초 후, 당신은 당신이 한 일을 후회하게됩니다. 그 다음, foo.h에있는 인라인 된 단어를 다시 foo.cc으로 옮기고 inline 키워드를 다시 제거하십시오.

    그러나 선언과 정의가 함께 사용되는 경우에는 그렇게하지 않아도됩니다.

그리고 이런 종류의 사소한 두통이 있습니다.

당신이 선언과 함께 함수의 정의를 작성하면 컴파일러가 함수의 프로토 타입을 유추 할 수 없다는 생각이 들게됩니다.

예를 들어, 예를 들어, 단지

#include_typedef "source.cc" 

것들의 형식 정보를 하나의 source.cc을 사용하고 가져가 간단 할 것입니다. 컴파일러가 AST를 구성하기 전에 파서 시간에 필터 만 사용하여 변수 할당 및 함수 정의를 무시하는 것이 쉽지 않은가요?

필자는 별도의 소스/헤더 파일로 프로그래밍하는 데 익숙하지만 필자는 분리를 확실히 할 수 있습니다. 프로그래밍 스타일에 대해 논할 수는 있지만 논리가 더 나은 프로그래밍 스타일로 표현되는 올바른 방법이 무엇인지에 대한 질문을 저하시킵니다. 소스/헤더 분리 컨텍스트에서 Java가 더 나은 프로그래밍 스타일이라고 생각하지 않습니다. 하지만 자바는 올바른 방법을 제공합니다.

헤더와 클래스를 분리 하시겠습니까? 가능하면 어떻게 하나로 섞을 것입니까? 선언과 정의를 혼합 된 소스에서 별도의 파일로 분리 할 수있는 C++ 프런트 엔드가 있습니까? 또는 어떻게 그런 글을 쓸 수 있습니까? (필자는 GCC를 의미한다.)

편집

내가 C를 강타하고 있지 않다 당신은이 질문에서 잘못된 정보를 얻는 경우 ++ 어쨌든, 미안 해요.

C++은 다중 패러다임 언어이므로 매직 매크로를 사용하여 MFC 설정 메시지 바인딩을 이해하고 템플릿을 사용하여 라이브러리가 모든 것을 구현하는 방법을 확인할 수 있습니다. 분리가 문제 영역으로 들어가면 (도메인이 패키징 시스템에 속해 있음을 알리는 ONeal에게 감사) 문제를 해결하는 방법을 찾아 낼 수 있습니다. 프로그래밍 스타일에는 많은 종류가 있습니다. C++ 프로그래밍에 많은 시간을 썼기 때문에, 어떤 작은 편의도 큰 편리함으로 축적됩니다. 선언과 함께 구현을 작성하는 것이 편리합니다. 나는 그들을 분리 할 필요가 없으면 적어도 10 %까지 소스 라인을 줄일 수 있다고 생각한다. 편리하다면 자바를 사용하는 것이 왜 중요할까요? C++이 Java와 다르다는 것은 분명합니다. 상호 교환 할 수 없습니다.

인라인 함수는 문제를 해결할 수 있지만 의미를 전혀 변경하지 않습니다.

+4

그렇다면 [C++ book] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)에서 배우고 계신가요? 문제를 잘못 진단했습니다. * 헤더 가드 *가 필요합니다. (그리고 선언문에서 기본값을 지정하십시오. 그래서 첫 번째 문장을 지정하십시오.) 이러한 질문은 C++ 책에 의해 응답되어야합니다. – GManNickG

+2

'foo.h'에 포함 된 가드가 없기 때문에'Foo 클래스의 재 선언 '을 얻은 이유가 있습니다. '.h' 파일에 구현체를 포함시키는 것과 아무런 관계가 없습니다. –

+1

그리고'.c' 파일에 C++ 코드를 제공하면 컴파일러가 잘못된 것을하도록 요청하는 것입니다. – jalf

답변

2

선택적 매개 변수에 대한 기본값은 어디에 제공됩니까?

헤더 파일. 기본 인수는 호출 사이트에서 주입되는 구문 설탕입니다. 정의 지점에서 그들을 제공하는 컴파일해야합니다.

인라인 간 이동 & 인라인 ... 아닌가요?

두 가지에 따라 달라집니다 : 당신이 전체 프로그램 최적화를 지원하는 컴파일러가있는 경우 A. 경우 성능 문제를,와 B (GCC 및 MSVC 모두) 다른 사람에 대한이 (확실하지 않은 지원 ++; 또한 "링크 타임 코드라고 세대"). 컴파일러가 LTCG를 지원하지 않으면 컴파일러가 각 변환 단위의 코드에 대해 더 많이 알기 때문에 헤더 파일에 함수를 추가하여 성능을 향상시킬 수 있습니다. 성능이 중요하지 않으면 가능한 한 구현 파일에 넣으십시오. 이런 식으로, 약간의 구현을 변경하면 전체 코드베이스를 다시 컴파일 할 필요가 없습니다. 반면 컴파일러가 LTCG를 지원한다면 컴파일러가 모든 변환 단위를 한꺼번에 최적화하기 때문에 성능면에서도 문제가되지 않습니다.

헤더와 클래스를 구분 하시겠습니까? 가능하다면 어떻게 하나로 섞을 것입니까?

Java/C#/friends 패키지 시스템에는 장점이 있으며 C++의 포함 시스템에는 장점이 있습니다. 불행히도 C++의 경우, 메모리가 산재 해있는 머신은 Java/C#의 시스템을 아마 더 좋게 만들었습니다. 이와 같은 패키지 시스템의 문제점은 주어진 시간에 메모리에 전체 프로그램 구조를 유지할 수 있어야한다는 것입니다. 반면 포함 시스템에서는 주어진 시간에 메모리에 단일 변환 단위 만 있어야합니다. 이것은 평균적인 C++이나 Java 프로그래머에게는 문제가되지 않지만, 수백만 라인의 코드베이스를 컴파일 할 때, C++과 같은 일을하면 상당히 낮은 스펙의 머신에 필요했을 것입니다. 1972 년에 실행). 요즘에는 프로그램 데이터베이스를 메모리에 보관하는 것이 비실용적이지 않으므로이 제한 사항은 더 이상 실제로 적용되지 않습니다.그러나 우리는 이러한 종류의 것들을 최소한 잠시 동안 붙잡겠습니다. 언어가 구조화 된 방식이기 때문입니다. 아마도 C++ 언어의 향후 개정판에는 패키징 시스템이 추가 될 것입니다. C++ 0x 이후에는 적어도 하나의 제안이 있습니다.

프로그래머가 "마음"을 생각하면 두 시스템 중 하나를 사용해도 상관 없습니다. C++의 클래스 선언과 함수 정의의 구분은 들여 쓰기 수준을 저장하기 때문에 때로는 좋습니다.

+0

LTCG가 흥미 롭습니다. 당신이 말했듯이, 휴대용이 아닐 수도 있습니다. 그러나'인라인'사용에 대한 나의 의도는 왜 분리가 좋지 않은지 설명하는 것입니다. 저는 C++ 0x로 자주 옮겨 가야한다고 생각합니다. –

+0

@ 谢 渡雷 : 만약 당신이하고있는 일이 C++을 배시하려고한다면 당신은 다른 공동체로 이동할 수 있습니다. 우리는 여기에 관심이 없다. 특히 우리가 당신을 위해 질문에 대답하기 위해 시간을 보내고 있습니다. –

+0

'C++ 0x 이후에 적어도 하나의 제안이 있습니다.'어느 것입니까? –

5

이 질문을 통해 일반적인 C++ 컴파일 시스템의 근본적인 단점을 보완하게됩니다. 그러나 그 것을 뒷받침하게하면, 첫 번째 예에서 무언가가 깨져있는 것처럼 보입니다. 실제로 모든 수업을 완벽하게 인라인하는 스타일은 완벽하게 작동합니다. 템플리트를 사용하여 작업을 시작하는 순간, 작업을 수행하는 유일한 방법이기도합니다. 예 : 부스트 라이브러리는 대부분 헤더 일 뿐이며 가장 관련이있는 기술 정보조차도 인라인으로 작성됩니다. 그렇지 않으면 작동하지 않기 때문입니다.

내 생각 엔 헤더 가드을 놓친 것이므로 재정의 경고가 표시됩니다.

// foo.h -------- 

#ifndef FOO_H 
#define FOO_H 

class Foo { 
    void bar() { ... } 
}; 

#endif // FOO_H 

이 잘 작동해야

+1

또는 #pragma once를 사용하십시오.) +1 –

+0

OP의 특정 오류가 수정되었지만 질문의 본문에서 묻는 질문에 답변을하지 못했습니다. ( –

+2

@ J-16 : 헤더 가드가 표준이거나, #pragma once가 아니다 – jalf

2

당신이 준 첫 번째 예는 ++ 사실 C 완벽하게 유효하다; 클래스 선언 본문에 정의 된 함수는 사용자가 inline으로 정의한 것과 같습니다. 컴파일러 만 첫 번째 복사본을 보았는지 확인하기 위해 일종의 포함 가드없이 .h를 두 번 포함시켜야합니다. 당신은 본 수도 이전 :

#ifndef FOO_H 
#define FOO_H 1 
... 
#endif 

이 foo.h 두 번 포함 된 경우 두 번째 사본이 FOO_H가 정의되어 있는지 보는 것을 보장하므로 코드를 건너 뜁니다.

기본 매개 변수는 .cc (.cpp)가 아니라 .h에 선언되어야합니다. 그 이유는 컴파일러가 호출 코드가 컴파일 될 때 모든 매개 변수로 전체 함수 호출을 작성해야하므로 호출 시점의 모든 기본 매개 변수의 값을 알아야합니다. 코드 정의에서 다시 정의하는 것은 중복되며 일반적으로 오류로 처리됩니다.

+0

+1보다 나은 기본 설명에 대한 설명. –

+0

예, FOO_H를 사용하는 방법을 알고 있습니다. C++을 10 년 이상 프로그래밍했습니다. 인라인은 모든 문제를 해결할 수 있지만 인라인은 충분하지 않습니다. 인라인은 소스 파일과 헤더 파일을 혼합하는 대신 최적화를 위해 설계되었습니다. –

+0

선택적 인수가 좋은 예가 아닐 수 있습니다. 분리로 인한 다른 작은 문제가 있습니다. 필자는 소스에서 별도의 헤더를 사용하여 빠른 컴파일, 적은 파일 구문 분석,/usr/share/include/compact and simpler를 만듭니다. 하지만 수동으로 두 파일을 유지 관리하는 대신 포함 파일을 생성하는 것이 더 좋습니다. –

관련 문제