2013-10-15 4 views
2

다양한 지루한 이유로, int로 주로 작용하는 boxed int 클래스가 필요하지만 객체 계층의 다른 부분과도 작업 할 수 있도록 기본을 상속하는 클래스입니다. int, int 캐스팅을 포함하는 생성자를 포함하여 boxed int와 코드의 일반 int를 쉽게 섞을 수 있습니다. 그러나 나는 알 수없는 매우 이상한 행동을보고 있습니다. 함수에서 boxed int를 반환하면 다른 BoxedInt에 대한 참조를 사용하는 복사 생성자를 사용하고 싶습니다. 그러나 대신 내 boxed int 및 int, 캐스팅하고 내 int 생성자를 사용합니다. 이것은 실제 코드베이스에서이 경우 복사하려는 다른 baseclass 속성이 있고이 캐스트/생성자 경로를 가져 와서 손실되기 때문에 문제가 발생합니다. 여기에 문제의 코드입니다 : 내가 다른 하나 개의 값을 할당 할 때 내가 원하는만큼, 레퍼런스 기반의 생성자가 사용된다 그래서C++에서 반환 값을 int로 변환하도록 선택하는 이유는 무엇입니까?

Start 
Constructed with int 
Copying 
Constructed with reference 
Assigning from return value 
Constructed with int 
Constructed with reference 
Cast to int 
Constructed with int 
Done 

:이 실행

class BoxedInt 
{ 
private: 
    int m_int; 
public: 
    BoxedInt():m_int(0) 
    { 
     trace(L"Constructed with nothing"); 
    } 

    BoxedInt(int val):m_int(val) 
    { 
     trace(L"Constructed with int"); 
    } 

    BoxedInt(BoxedInt& val) 
    { 
     trace(L"Constructed with reference"); 
     m_int = val.m_int; 
    } 

    operator int() 
    { 
     trace(L"Cast to int"); 
     return m_int; 
    } 
}; 

BoxedInt funky() 
{ 
    BoxedInt TempInt = 1; 
    return TempInt; 
} 

int main(int argc, char* argv[]) 
{ 
    trace(L"Start"); 
    BoxedInt test1 = 1; 
    trace(L"Copying"); 
    BoxedInt test2 = test1; 
    trace(L"Assigning from return value"); 
    BoxedInt test3 = funky(); 
    trace(L"Done"); 
    return 0; 
} 

, 여기에 출력의 배고 있다. 그러나, 내 함수의 반환 값을 BoxedInt에 할당하면 컴파일러가 int로 변환하고 int 생성자를 사용하기로 결정합니다. 내 C++은 녹슬었고 나는 이상한 컴파일러 결정의 최하점에 도달하는 데 어려움을 겪고있다. 어떤 아이디어?

+0

명시 적 키워드 http://stackoverflow.com/questions/121162/what-does-the-explicit-keyword-in-c-mean에 대한 설명 – fasked

+0

컴파일러는 ** 반환 값을' int', ** ** 그것을 변환합니다. 캐스트는 컴파일러에게 변환을 지시하기 위해 소스 코드에 작성하는 것입니다. 마찬가지로 '연산자 int'는 ** 변환 연산자 **가 아니라 캐스트입니다. –

답변

9

, 그렇게해야한다 :

+2

나는 바보 같은 기분이 들지만 나는 게시하자 마자 그걸 알아 차렸다.하지만 지우는 것은 너무 늦었다! 너희들 너무 빠르다. –

+0

@Raja 참고할만한 좋은 페이지인지 잘 모르겠습니다. 허브는 문제를 잘 설명하지만, 그가 사용하는 예제는 시작, const 또는 기타로 참조를 사용해서는 안되는 경우입니다. 그가 이것에 대해 아무것도 말하지 않는다는 사실은 많은 독자들에게 여기에서 const 참조를 사용하는 것이 좋은 프로그래밍 습관이라고 제안 할 수 있습니다. –

+0

좋은 점 제임스. 링크를 삭제했습니다. – Raja

5

복사 생성자는 const가 아닌 참조를 취합니다. 즉, 매개 변수에 임시를 바인딩 할 수 없으므로 원하는 반환 방법이 수행하는 것입니다. 따라서 컴파일러는 다른 경로를 선택합니다. 사실

BoxedInt(const BoxedInt &val) { 

, 연타 3.4 때문에 BoxedInt test1 = 1;gives an error :

은 복사 생성자를 변경

.

BoxedInt(BoxedInt& val) 

그것은 귀하의 복사 생성자가 const가 아닌 참조 소요

BoxedInt(const BoxedInt& val) 
+1

나는 Clang이 옳다고 생각한다. 복사 초기화에는 액세스 가능한 복사 생성자가 필요합니다. 그리고 이것을 해석 할 수있는 방법은 최소한 이론적으로 구성된 임시 복사본을 복사 할 수있는 복사 생성자를 의미합니다. –

+0

@JamesKanze, 전적으로 동의합니다. – chris

+2

GCC 4.8.1 또한'BoxedInt test1 = 1;'에 불평합니다. –

1

나는 문제 (또는 그 중 하나) 복사 생성자 서명 믿습니다 임시 전화로 을 호출 할 수 없습니다. funky()의 반환 값은 임시이므로 복사 생성자는 을 사용하여 test3을 생성 할 수 없습니다.

복사 생성자가 const 참조를 취하게하고 을 확인해야합니다.