2011-09-07 20 views
5

는 두 개의 별도의 헤더 파일에 있고 임의의 순서로 나타날 수 있습니다C++ 클래스 프로토 타입 충돌

//TestB.h 
class TestB; //Forward declaration for a later operator= in a centralised header 

class TestA 
{ 
    const TestA&operator=(const TestB); //defined in Test.h 
}; 

그리고 :

//TestA.h 
class TestA; //Forward declaration for a later operator= in a centralised heaer 

class TestB 
{ 
    const TestB&operator=(const TestA); //defined in Test.h 
}; 

가 어떻게 프로토 타입 충돌을 방지합니까?

도움을 주시면 감사하겠습니다.

전적으로 사과드립니다. 내가 거기에 대한 참조 (연산자 = 앰퍼샌드 - 인자 - 나는 바 간단한 POD를 복사하여 통과 결코)에 대한 의도와 프로토 타이핑 갈등에 대한 질문을 의미! 나는 그것이 증명 - 독서의 중요성을 보여주는 것으로 간다! 나는 오리지널 (틀린) 맥락에서 주어진 답을 받아 들였다.

나는 단 몇 분만 돌렸고 잘못을 알지 못했습니다!

+1

"프로토 타입 충돌"이란 무엇입니까? –

+2

여기에 아무 문제가 없습니다. 정상적으로 작동합니다. 오류를 더 잘 설명하고 실제 코드를 설명해야합니다. –

+1

@Als : 불완전한 형식을 취하는 함수를 값으로 선언 할 수 있습니다. 타입 정의 후에 만 ​​정의하거나 호출 할 수 없습니다. –

답변

4

매개 변수로 클래스에 대한 참조를 전달합니다. 이렇게하면 클래스와 그 멤버 함수는 다른 클래스에 대해 알지 못해도 선언 될 수 있습니다.

//TestB.h 
class TestB; //Forward declaration for a later operator= in a centralised header 

class TestA 
{ 
    const TestA&operator=(const TestB &); //defined in TestB.h 
}; 

그리고이 후

//TestA.h 
class TestA; //Forward declaration for a later operator= in a centralised heaer 

class TestB 
{ 
    const TestB&operator=(const TestA *); //defined in TestA.h 
}; 

, 이러한 멤버를 정의 할 수 있도록 모두 TestA.cpp 및 TestB.cpp 파일에 TestA.h 및 TestB.h를 모두 포함해야합니다 기능.

+0

의미론을 바꿀 필요가 없다. * 당신이 * 정의 *하려고하지 않는 한 ** 불완전한 타입 *을 값으로 취하거나 반환하는 함수를 선언 할 수있다. * 해당 함수를 호출합니다. –

4

내 원래 대답은 완전히 틀린 것 같습니다.

무한 사슬로 끝나지 않도록 모든 헤더 파일에 가드가 포함되어 있는지 확인하십시오. 그런 다음 각 구현 헤더 포함 : 이러한 구조가 호기심 설계 상황을 만드는

// A.cpp 
#include "A.h" 
#include "B.h" // for complete type TestB 

const TestA & TestA::operator=(const TestB) { /* ... */ } 

// B.cpp 
#include "B.h" 
#include "A.h" // for complete type TestA 

const TestB & TestB::operator=(const TestA) { /* ... */ } 

을 유의하시기 바랍니다 어디 반드시 포함해야 연산자를 호출하고 싶다고 중 하나 TestA 또는 TestB의 소비자 A.hB.h 모두 매우 세분화되어 있지만 예기치 않은 비트입니다. 두 개의 헤더 파일을 모두 포함하는 클라이언트에서 사용할 중간 헤더 파일을 추가하거나 헤더 파일 자체에 상호 포함 (가드 포함)을 추가하는 것이 유용 할 수 있습니다. 당신이 플랫 아웃 재귀 무한 의존성을 가지고 있기 때문에


당신은, 당신이 그것을 쓴 방법으로이 문제를 해결할 수 없습니다.

당신이 보통이 참조로 전달하기 때문에, 참조 복사가 아닌하여 인수를 통과하는 것입니다 방법 하지이 전체 유형의 지식이 필요합니까 :

const TestA & operator=(const TestB &); 
            ^^^^^ 
            vvvvv 
const TestB & operator=(const TestA &); 

+2

인수 유형이 불완전하더라도 값을 기준으로 인수를 사용하는 함수를 선언 할 수 있습니다. 클래스 정의 후에 만 ​​함수를 정의 할 수 있습니다. –

+0

@Mike : 나는 놀랐다, 나는 그것이 정말로 허용되지 않는다고 생각했다! –

+0

@Kerrek SB : 함수가 헤더 파일에서 * 정의 * 또는 * 호출되지 않는 한 순환 포함을 추가 할 필요가 없으며 해당 멤버를 호출 * 또는 * 정의하는 번역 단위 함수는 두 헤더를 모두 포함합니다. –

0

전달 선언은 포인터 선언과 유형에 대한 참조에만 유용합니다. 실제 복사 작업에는 사용할 수 없으며 클래스 인스턴스를 정적이 아닌 클래스 데이터 멤버로 선언 할 수 없습니다. 그렇게하려고하면 컴파일러는 불완전한 타입에 대한 에러를 줄 것입니다. 왜냐하면 실제 타입이 무엇을 구성하는지에 대한 정보를 컴파일러에게주기에 충분한 정보가 없기 때문입니다.), 메인 클래스를 구성하거나 클래스의 메소드 인수 중 하나에 할당 할 스택 공간을 결정할 수 있습니다.

1

을 선언하고 정의를 제공하지 않는 한 실제 헤더에 문제가 없습니다. 즉, 멤버 함수에 대한 정의가 두 헤더를 모두 포함하는 .cpp 파일에 있고 두 함수 중 하나에 대한 호출이없는 경우 완벽하게 작동해야합니다.

당신은 앞으로 선언 유형 처럼 보이는 아무것도 사용할 수없는 일반적인 오해가있다, 사실은 당신이 당신에게 을 해당 유형의 객체를 만들거나 해당 유형의 멤버 변수를 만들 수 있지만 수 있다는 것입니다 값으로 유형을 사용하거나 반환하는 함수를 선언 할 수 있습니다. 즉, 불완전 타입의 객체의 생성을 필요로하기 때문에

당신은, 다른 한편으로는, 또는 전화 이러한 기능을 정의 할 수 없습니다.