2013-06-07 3 views
0

왜이 프로그램이 아래 출력을 생성하는지 이해할 수 없습니다.C++ const char * overloading confusion

void blah(const char*)  {printf("const char*\n");} 
void blah(const std::string&) {printf("const string ref\n");} 
template<class t> 
void blah(t)     {printf ("unknown\n");} 

int main(int, char*) 
{   
    blah("hi"); 
    char a[4]; 
    blah(a); 
    std::string s; 
    blah(s); 
    getch(); 
} 

출력 : VS2008에서

const char* 
unknown 
const string 

. std :: string을 const 참조로 변환하려고하지만 char *을 const char *로 변환하지 않고 왜 오버로드를 사용합니까?

+1

간단히 말해서 가장 비슷한 옵션을 지정하면됩니다. 'class t'는 변환이 필요없는'char *'와 정확히 일치 할 수 있으므로 선호하는 것을 선택합니다. – Dave

+0

(덧붙여 말하자면,'string' 예제는 참조로 변환되지 않고, 참조로 전달되는 것이 기본값이며, 일치하는 것이없는 경우에만 패스 - 바이 - 카피가됩니다.) 템플릿은 참조 - (rvalue 참조에 대한 특별한 경우 제외), 템플릿은 복사본으로 만 클래스를 받아 들일 수 있습니다. – Dave

+0

문자열이 "참조로 전달되는 기본값"이라는 것은 무엇을 의미합니까? 't' 타입이'std :: string &'이 될 수없는 이유는 무엇입니까? 나에게 맞는 것은 두 가지 호출이 모두 정확히 일치한다는 것입니다. 'string'도'char *'도'const'가 아닙니다. –

답변

3

"hi"의 유형은 const char[3]이며, a의 유형은 char[4]입니다.

따라서 첫 번째 호출은 배열 - 포인터 변환 (별칭 : "부패") 만 필요합니다. 세 번째 호출은 참조에 대한 참조에 객체를 바인딩하는 것만을 요구합니다 (내가 잘못 생각할 수도 있지만 "변환"은 참조 바인딩의 올바른 용어라고 생각하지 않습니다). 두 번째 호출은 const char* 과부하를 호출하기 위해 배열 감쇠 을 포인터 변환이 필요합니다.

표준에서 과부하 해결 텍스트를 실제로 확인하지 않고이 추가 단계를 수행하면 템플릿이 const char* 오버로드보다 더 나은 일치를하게됩니다.

Btw, "unknown\n""%s\n", typeid(t).name()으로 변경하면 t이 어떤 것으로 추측되었는지 알 수 있습니다. 코드의 경우 char*으로 추측되지만 배열을 값으로 전달할 수 없기 때문에 t 대신 t& 매개 변수를 사용하도록 템플릿을 변경하면 어떻게되는지 확인하십시오. 그러면 tchar[4]으로 추론 할 수 있습니다.

+0

잘못된 것 같습니다. 'blah ((char *) "hi")'는 여전히'unknown'을 생성합니다. –

+0

@TysonJacobs 물론 그렇습니다. 'blah ((const char *) a)'는'const char *'를 생성합니다. * explicit * 형 변환은 함수 해석 전에 발생하기 때문에 함수 호출은 그것을 변환해야합니다 * back *! – Dave

+0

@Dave 그러나 포인터는 배열을 포인터로 변환하고 포인터 유형을 변환해야했기 때문에 템플릿이'blah ("hi")'에 대한 호출과 일치한다는 것이 핵심이었습니다. 'char *'에 캐스팅하면 이러한 단계 중 하나가 제거됩니다. –