2011-01-12 12 views
16

이 오류 메시지는 무엇을 의미합니까?오버로드 된 함수 호출이 모호합니다.

error: call of overloaded ‘setval(int)’ is ambiguous 
huge.cpp:18: note: candidates are: void huge::setval(unsigned int) 
huge.cpp:28: note:     void huge::setval(const char*) 

내 코드는 다음과 같습니다

#include <iostream> 
#define BYTES 8 
using namespace std ; 

class huge { 
private: 
    unsigned char data[BYTES]; 
public: 
    void setval(unsigned int); 
    void setval(const char *); 
}; 

void huge::setval(unsigned int t) { 
    for(int i = 0; i< BYTES ; i++) { 
     data[i] = t; 
     t = t >> 1; 
    } 
} 

void huge::setval(const char *s) { 
    for(int i = 0; i< BYTES ; i++) 
     data[i] = s[i]; 
} 

int main() { 
    huge p; 
    p.setval(0); 
    return 0; 
} 
+4

이 질문에 대한 대답은 당신이 호출하려고하는 함수의 버전에 달려 있다고 생각합니다. 나는 추측 할 수는 있지만, 분명히 말해주지 않으면 어느쪽으로 든 확신 할 수 없다. 컴파일러에서 작동하는지 궁금합니다 ... –

+0

@KonradRudolph 리터럴 '0'은 'unsigned int'와 'const char *'모두에 유효한 값입니다. –

+0

@ RyanP 예, 일반적으로 알고 있습니다. 그때 내가 무엇을 의미하는지 모르겠다. –

답변

17

리터럴 0에는 C++의 두 가지 의미가 있습니다.
한편으로는 값이 0 인 정수입니다.
반면에 그것은 NULL 포인터 상수입니다.

setval 함수가 int 또는 char* 중 하나를 채택 할 수 있으므로 컴파일러는 사용자가 의도 한 과부하를 결정할 수 없습니다.

가장 쉬운 해결책은 0을 올바른 유형으로 캐스팅하는 것입니다.
또 다른 옵션은 다른 하나를 템플릿을함으로써 int 과부하 예를 들어, 선호되어 있는지 확인하는 것입니다

class huge 
{ 
private: 
    unsigned char data[BYTES]; 
public: 
    void setval(unsigned int); 
    template <class T> void setval(const T *); // not implemented 
    template <> void setval(const char*); 
}; 
+0

가치가있는 부분에 대해서는 클래스 선언 외부에서 특수화를 포함해야했습니다. 기본적으로'template <> void huge :: setval (const char *);를 클래스 선언 바로 아래에 포함하십시오. 그렇지 않은 경우 클래스 범위에서 템플릿을 전문화하는 데 대한 오류가 발생했습니다. 위대한 트릭이지만, 이것은 내 인터페이스의 일부로 전에 나를 괴롭혔다. – vmrob

+1

'0'은 C++에서 단 하나의 의미만을가집니다. 이것은'int' 형의 정수형 리터럴입니다. OP가 실제로 int를 취하는 과부하와 char *를 취하는 또 다른 오버로드를 가진다면, 과부하 해결은 성공할 것이고'int' 과부하를 선택하게 될 것입니다. 그러나 OP는 'unsigned int'를 매개 변수 유형으로 사용합니다. 그리고이 두 변환 'int' ->'unsigned int'와 널 포인터 상수 ->'char *'는 모호합니다. – dyp

+0

@dyp : '0'에 의미가 하나뿐이라면 어떻게 시작 유형이 다른 두 개의 모호한 변환에 참여할 수 있습니까? –

1

사용

p.setval(static_cast<const char *>(0)); 

또는 오류로 표시된 바와 같이

p.setval(static_cast<unsigned int>(0)); 

0의 유형 int입니다. 이것은 unsigned int 또는 const char *으로 쉽게 캐스팅 할 수 있습니다. 수동으로 캐스트를 작성하면 컴파일러에게 원하는 오버로드를 알려줍니다. 값이 컴파일러가 알 수 있도록

1

캐스트는 전화 기능 : 당신이 (따라 컴파일에 도착 후 코드에서 세그먼트 오류가 있는지,

p.setval(static_cast<const char *>(0)); 

참고하는에 정말 전화하고 싶었 기능).

3

p.setval(0);을 다음으로 대체하십시오.

const unsigned int param = 0; 
p.setval(param); 

그런 식으로 상수 0이 어느 유형인지 확실히 알 수 있습니다.

2

포인터가 단지 주소이기 때문에 모호합니다. 따라서 int는 포인터로도 처리 될 수 있습니다. 0 (int)은 unsigned int 또는 char *로 쉽게 변환 될 수 있습니다.

짧은 대답은 p.setval()이 구현 된 유형 중 하나 인 unsigned int 또는 char *로 분명하게 호출하는 것입니다. p.setval (0U), p.setval ((unsigned int) 0) 및 p.setval ((char *) 0)이 모두 컴파일됩니다.

이러한 유형의 오버로드 된 함수를 정의하지 않는 것이 일반적으로이 상황을 피하는 것이 좋습니다.

+0

+1 특히 마지막 단락. –

+0

C++ 0x를 기다릴 수 없습니다. nullptr 키워드를 마침내 갖습니다. –

+0

p.setval ((char *) 0)은 컴파일되지만 응용 프로그램이 충돌합니다. p.setval (0U)는 잘 작동합니다. – Rajesh

12

우리는 "서명해야 상수 값의 유형을 고려하는 경우이 솔루션은 매우 간단합니다 int "대신"int "를 사용하십시오.

setval(0) 

사용 : 대신의

setval(0u) 

접미사 "u는"이것은 부호없는 정수입니다 컴파일러를 알려줍니다. 그런 다음 변환이 필요하지 않으며 호출이 모호합니다.

+1

우수 답변, 간단하고 우아한 방법으로 컴파일러에게 알립니다. –