2010-12-16 3 views
1

이것은 google's c++ coding guidelines에서 발췌 한 것입니다.정의에 액세스하지 않고 헤더 파일에서 클래스를 사용합니까?

헤더의 정의에서 Foo 클래스를 어떻게 사용할 수 있습니까?

  • Foo * 또는 Foo & 유형의 데이터 멤버를 선언 할 수 있습니다.
  • 인수를 사용하여 함수를 선언 할 수 있지만 Foo 유형의 반환 값을 선언 할 수 있습니다. (한 예외는 인수 푸 또는 const를 푸 & 우리가 지원 자동 타입 변환에 대한 전체 정의를 필요로하는 경우가 아닌 명시 적, 한 인수 생성자가있는 경우입니다.)
  • 것은 우리는 정적 선언 할 수 있습니다 Foo 유형의 데이터 멤버. 그 이유는 정적 데이터 멤버가 클래스 정의 외부에서 정의 되었기 때문입니다.

궁금한 점은 두 번째 글 머리 기호에서 예외입니다. 이게 왜 그렇게? 자동 유형 변환을 지원하려면 전체 정의가 필요한 이유는 무엇입니까?

내 생각에 암시 적 변환시 생성 된 임시 개체 때문에 컴파일러에서 대상 형식의 전체 정의가 필요합니다. 나는 정확하게 추측하고 있는가? 더 많은 것이 있습니까?

편집 : 제가보기에는

, 가이드 라인에서 예외가 같은 상황으로 주소 :

여기
class A 
{ 
    public: 
     A(int); 
}; 

class B 
{ 
    public: 
     B(A const &a); 
}; 

int main() 
{ 
    B b(2); 
} 

우리 (A까지 INT에서) 하나의 사용자 정의 암시 적 변환이 const &을 허용하는 생성자를 호출합니다. 이 예외에서 의미가있는 것은 직접 변환을 지원하는 것입니다. int를 A로, 그리고 B를 const &을 수락하는 생성자를 통해 전달함으로써 A 클래스가 선언 된 헤더 파일을 명시 적으로 포함 할 필요없이 클라이언트 코드가이 변환 체인을 사용할 수 있도록합니다.

+1

-. 임시 개체에 대한 걱정도 전에 컴파일러는 암시 적 변환을 허용하기 전에 생성자가 존재한다는 것을 알 필요가있다. 하지만 그렇습니다. 컴파일러는 임시/인수 공간을 할당하고 생성자를 호출하는 코드를 생성해야하므로 크기 및 생성자 선언이 필요합니다. –

+0

컴파일러가 변환 할 수 있음을 알기에 충분한 생성자의 선언 및 소스 유형 선언이 아닙니까? 그래도 답장을 보내 주셔서 감사합니다. – LavaScornedOven

+0

@Vedran : 네, 스티브가 말한 것입니다. Google 가이드 라인의 경우 가이드 라인의 규칙 예외가 의미가 없음을 의미합니다. 지침은 "[클래스] 정의에 대한 액세스 권한 없음"에 대해 이야기합니다. 이 경우 크기 나 생성자 정의가 알려져 있지 않습니다. 그래서 그것은 문제가 아닙니다. –

답변

0

foo.hfoo.cpp

// foo.cpp 

class CanBeConvertedToFoo; 
class Foo 
{ 
    Foo (const CanBeConvertedToFoo & x); // implicit constructor 
} 

class CanBeConvertedToFoo 푸에 암시 convertable입니다 만

//foo.h 

class Foo; 
void f(const Foo &); // It is possible to use the reference. 

전체 정의는 약 Foo 선언을 알고 있다고 가정; 그러나 이것은 some.cpp에서 알 수 없습니다.

// some.cpp 

#include "foo.h" 
void g(const CanBeConvertedToFoo & x) { 
    f(x); // Is it known about implicit conversion ? 
} 
+0

즉,'g '의 정의는'CanBeConvertedToFoo'의 정의가 필요하지만'Foo'의 정의는 그렇지 않습니다. – Philipp

+0

+1이 해석은 Steve의 설명과 연결된 이름 조회 수준에 있습니다. 앞서 언급 한 규칙에 그러한 예외를 도입하려는 동기를 발견 할 수 있습니까? – LavaScornedOven

+0

-1이 경우에는 "g"함수를 "선언 (정의하지 않음)"할 수 있습니다. Google 지침에 따라 'g'가 '예외'가되는 것은 아닙니다. 그래서 이것은 "예외"가 의미하는 바를 대답하지 못합니다 : 그것은 구글 주장이 의미없는 한가지 방법만을 보여줍니다. –

0

두 번째 점의 예외가 true인지 여부는 알 수 없습니다. 암시 적 변환은 선언하지 않을 경우, 함수가 호출되는 경우에만 알고 있어야합니다, 그래서 다음은 f 선언하면서 C가 불완전하더라도 작동합니다

#include <iostream> 
class C; 
void f(C); 
struct C { C(int i) { std::cout << "C(" << i << ")" << std::endl; } }; 
void f(C c) { std::cout << "f(C)" << std::endl; } 
int main() { f(2); } 
2

는 C++ 언어 헤더에 코드를 구분하지 않습니다 파일 및 기타 파일. 헤더가 파일 일 필요는 없습니다.그래서 기술적으로 질문은 의미가 없지만 실제로는 헤더 정의 파일에서 수행하는 작업을 제한하여 One Definition Rule에 위배되지 않도록하십시오. 자신을 제한하지 않고 사용자는 헤더 파일을 하나의 번역 단위에만 포함 시키도록주의해야합니다. 적절한 제한 사항을 사용하면 헤더 파일을 여러 번역 단위에 자유롭게 포함시킬 수 있습니다.

불완전 유형은 크기를 알 수없는 곳이며, sizeof은 사용할 수 없습니다.

클래스 정의를 알 수없는 경우 클래스 Foo은 반드시 불완전합니다.

이것은 크기를 알 필요가있는 작업을 수행 할 수 없다는 것을 의미합니다. 그리고 불완전 성은 회원이 알려지지 않았기 때문에 (크기가 알려졌다면 반드시 알려질 것입니다) 일반적으로 회원을 부를 수는 없습니다. 예외 : delete pFoo과 같이 소멸자를 호출 할 수 있습니다. 컴파일러는이를 받아 들여야합니다. 그러나 Foo에 사소한 소멸자가없는 경우에는 정의되지 않은 동작입니다.

그러나 Google 가이드 라인에서 언급 된 예외는 의미가 없습니다.

편집 : 나는 가이드 라인은 의미가 왜 의 토론을 추가, 그래서 같은 사람들이 일을 자세히에서 철자가 더 나은 경우 발견, 그래서.

지침은 "선언 (하지만 정의하지 않음)"하지만 "Foo 또는 const Foo & 인수가 하나의 인수가없는 생성자가있는 경우"는 예외입니다.

#include <iostream> 

struct Foo; 

Foo bar(Foo const&); // Declaration of function bar, works fine. 

struct Foo 
{ 
    int x_; 
    Foo(int x): x_(x) {}  // Converting constructor. 
}; 

int main() 
{ 
    std::cout << bar(42).x_ << std::endl; 
} 

Foo bar(Foo const& foo) { return foo; } 

은 결론적으로, 다시, 구글 가이드 라인 '예외가 의미가 :

선언은 하나가 단순히 그것을 밖으로 시도하여 단언 할 수 생성자와 아무 상관이 없습니다.

건배 & HTH,

내가 덜이 말하고 싶지만
+1

나는 괄호 안에있는 예외가 무엇인지 너무 혼란 스럽다. 필자가 이해할 수있는 한, 암시 적 변환이있는 경우 인수가있는 함수와 Foo 유형의 반환 값을 선언 (* 정의 할 수 없음) 할 수 없음을 나타냅니다. 그러나 그것은 틀렸고 분명히 그렇습니다. 그래서 나는 그것이 의미하는 바를 배제합니다. 나는 그들이 묘사하지 않은 특정 유즈 케이스에 대해서 이야기하고 있지만 독자에게는 알지 못한다는 사실을 깨닫고 있다고 생각한다. 물론 "예외적 인"경우에는 다른 모든 경우와 마찬가지로 클래스 정의가 필요한 호출 코드입니다. –