2011-01-12 14 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++で2つの意味があります。
一方、値が0の整数です。
一方、NULLポインタ定数です。

setval関数はintまたはchar*のいずれかを受け入れることができるため、コンパイラはどの過負荷を意味するのかを判断できません。

最も簡単な解決策は、0を正しいタイプにキャストすることです。
別のオプションは、他の1にテンプレートを作成することにより、例えば、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++ではただ1つの意味しか持ちません。それはint型の整数リテラルです。 OPが本当に 'int'を使ってオーバーロードし、もう一つが' char * 'をとると、オーバーロードの解像度は成功し、 'int'過負荷を選択しました。しかし、OPは 'unsigned int'をパラメータ型として使用します。そして、これらの2つの変換、 'int' - >' unsigned int'とnullポインタ定数 - > 'char *'はあいまいです。 – dyp

+0

@dyp: '0'に意味が1つしかない場合、異なる開始型の2つのあいまいな変換にどのように関与できますか? –

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 *に同様に簡単に変換できます。

簡単な答えは、実装されている型のうちのひとつであるunsigned intまたはchar *で明白にp.setval()を呼び出すことです。 p.setval(0U)、p.setval((unsigned int)0)、およびp.setval((char *)0)はすべてコンパイルされます。

しかし、このようなタイプのオーバーロードされた関数を定義しないことで、この状況を避けるのが一般的には良い考えです。

+0

+1。 –

+0

最後にnullptrキーワードを持つC++ 0xを待つことはできません:) –

+0

p.setval((char *)0)はコンパイルされますが、アプリケーションがクラッシュします。 p.setval(0U)はうまく動作します – Rajesh

12

私たちは、「符号なしである必要があり、一定値の種類を考慮すれば、解決策は非常に簡単ですintの代わりにintを使用します。

setval(0) 

使用:代わりの

setval(0u) 

接尾辞 "U" は、これは符号なし整数であるコンパイラに伝えます。変換が必要なくなり、呼び出しは明白になります。

+1

ベストアンサー、コンパイラに伝えるシンプルかつエレガントな方法 –

関連する問題