2009-07-07 1 views
1

캐스팅을 사용할 때마다 결과 객체는 const 객체입니까?C++로 const 객체 생성하기

... 따라서 함수가 const 개체로 함수를 받아들이면 함수의 인수로만 사용할 수 있습니까?

class C1 { 
    public: C1(int i=7, double d = 2.5){}; 
}; 

void f(C1& c) {}; 

int main(){ 
    f(8); 
    return 1; 
} 
//won't compile 

답변

12

(F (...)의 값만큼의 인수를 수신하면 당연히 그 그것이 작동 할 수있는 비 CONST 버전 을 얻는다) 보통 때 특정 유형의 객체 다른 형식의 개체 (비표준 형식)로 변환되면 임시 개체가 만들어집니다 (const 개체가 아님). 임시 객체 (invisible, nameless, rvalue)는 (C++ 98/03에서) const 인 참조 ('예외 객체'라고 알려진 임시 참조 제외)에만 바인딩 할 수 있습니다. 따라서 임시를 만드는 변환 결과는 const 참조 또는 복사/변환 할 수있는 형식으로 받아들이는 함수의 인수로만 사용할 수 있습니다.

예 :

void f(double); // 1 
void f(const int&); // 2 
void f(int&); // 3 

struct B { B(int) { } }; 
struct C { C(int) { } }; 
void f(B b); // 4 
void f(B& b); // 5 
void f(const C& c); //6 
void f(C& c); // 7 

// D inherits from B 
struct D : B { D(int) : B(0) { } }; 
void f(D& d); // 8 

int main() 
{ 
    f((int) 3.0); // calls 2, NOT 3 
    f((float) 3); // calls 1 - const reference requires the same type 
    f(1); // calls 2, NOT 3 

    f((B) 1); // calls 4, not 5 - can accept it by non-const value 
    f((C) 1); // calls 6, not 7 - can accept it by const-reference 

    f((D) 1); // calls 4, not 8 - since a 'D' temporary object can be converted to a 'B' object - but will not bind to a non-const reference 
} 

희망이 있습니다.

+1

+1 : 나는이 대답을 좋아합니다. 따라서 각 전환의 순위와 종류를 지정하는 것이 유용 할 수 있습니다 (특정 버전이 다른 버전보다 왜 선택되었는지 보여주기 위해). 내가 옳다는 것을 확인해주세요. - 첫 번째 호출 (A) : 2 로의 완전 일치, 1 로의 변환 (B) 1로 승격, 2로 변환, (C) 2에서 완전 일치, 다음으로 변환 : A, B, C, 1. (D) 완전 일치 4. (E) 완전 일치 6. (F) 변환 (유도 -> 기본) - 4. 'const T'및 'T'의 모든 참조 바인딩에서 'const T'는 최상위 레벨의 const로 간주되어 rank (void f (T); void f (const T); f (T());'ambiguous)에 영향을 미치지 않습니다. –

+0

예. 바로 당신의 전환과 순위의 붕괴에 - 우리가 여기에서 다루었 기 때문에 또는 http://stackoverflow.com/questions/1092714/conversion-precedence-in-c/1092724#1092724, 나는 너무 많은 것에 집중하고 싶지 않았다. 오버로드 해결 -하지만 임시에 바인딩 할 수 있습니다 - 아마도 내가 다른 함수 이름을 사용해야하고 그것을 더 간단하게 보관해야합니까? –

+0

아, 알겠습니다. 나는 더 나은 것이 무엇인지 모른다. 그러나 나는 그것이 현재 어떻게 그것을 좋아한다.특정 버전이 특히 선호되는 이유를 알고 싶다면 다른 답변을 읽고 댓글 섹션을 살펴볼 수 있습니다. –

0

당신은 다시 작성할 수 있습니다과 :

class C1 
{ 
    public: C1(int i=7, double d = 2.5){}; 

}; 

void f(C1& c){}; 

int main() 
{ 
    C1 c(8); //named 
    f(c); 
    //... can access the modified C1 instance here ... 
    return 1; 
} 

버전에 대해 좋아하지 않는 컴파일러가 C1 인스턴스가 있다는 것을 것은 이름이 지정되지 않은 일시 : 그것 때문에 (수정되는 f하지만, 컴파일러는 호출자 (main)가 이러한 수정을 수신/보존/통지 할 방법이 없다는 것을 알고 있습니다.

3

'캐스팅'이라고 하기엔 다소 벗어났습니다. 당신은 '암시 적 건설'을하고 있습니다. 암시 적 생성은 항상 임시 객체를 만듭니다. 임시 객체는 항상 const입니다.

생성자를 '명시 적'으로 표시 할 수 있습니다. 그러면 여기에 표시되는 암시 적 생성 통화가 차단됩니다. 그러나 이것은 f (8) 대신에 f (C (8))가 필요하다는 것을 의미합니다. 임시 인스턴스이기 때문에 C 인스턴스는 여전히 const가 될 것입니다. 그러나 캐스트는 수행되지 않습니다.

정말로 필요한 경우 더러운 해결 방법은 const_cast를 참조하십시오. 다른 해결 방법은 두 개의 라이너를 수행하는 것입니다. C c (8); f (c);