2012-02-25 16 views
11

私はこの状況で混乱しており、グーグルが私に答えを与えていませんでした。基本的に私はコンパイルされません。次の簡単なコードがあります。これをコンパイルするにはオーバーロードされた静的関数へのあいまいな呼び出し

#include <iostream> 

class A 
{ 
public: 
    int a(int c = 0) { return 1; } 
    static int a() { return 2; } 
}; 

int main() 
{ 
    std::cout << A::a() << std::endl; 
    return 0; 
} 

を、GCC 4.2はmain()A::a()への呼び出しがa()有効な候補者の両方のバージョンで曖昧であると言います。 AppleのLLVMコンパイラ3.0はエラーなしでコンパイルされます。

gccはどの機能を呼び出したいのですが、なぜ混乱していますか? a()A::とすると、私はそれが機能のバージョンstaticを求めていることは明らかでした。 A::a()は、statica()を呼び出すための有効な構文ではないため、当然、static関数a()を削除すると、このコードはコンパイルされません。

ありがとうございました!

+0

私はすばらしいGoogle検索:「静的で非静的なメンバー関数の名前解決C++」は別のSOの質問を思いつきました:http://stackoverflow.com/questions/5365689/c-overload-static-function -with-non-static-function – Bingo

+0

私のgoogle-fuは私に失敗しました... – fang

答えて

6

これは、C++でこれがあいまいであると指定されているためです。オーバーロード解決はA::aのためにthisが範囲にないので、そのコールの引数リストは*thisの代わりに人為的なオブジェクトの引数によって増強されることを指定します。オーバーロードの解決は、引数リストが不自然なオブジェクトによって増大し、オーバーロードの解決はTの非静的メンバ関数のいずれかを選択している場合は、通話が悪い形成されている非静的メンバ関数を除外し、代わりに

ていません。

これは最近、core issue 1005の文脈での委員会での広範な議論の対象であった。 core issue 364を参照してください。これはこのルールの変更を検討しましたが、変更していませんでした。

+0

参考になりました。しかし、私はまだ理解しようとしていません。なぜ、「過負荷解決がTの非静的メンバー関数の1つを選択するのか」。あなたが言ったことを理解していれば、非静的なa()には2つの引数があります:これとデフォルト値(c = 0)の引数。静的なa()には、「作成されたAオブジェクトの引数」があります。コールで「this」ポインタを指定していないため、非静的バージョンを選択するのはなぜですか? – fang

+0

いいえ、 'this'はスコープにないので、' this'はこの呼び出しでは引数ではありません。それが私たちの呼びかけで "考案されたAオブジェクト引数"を渡す理由です。これらの関数の両方に暗黙的なオブジェクトパラメータがあります(スタティック関数の場合、そのパラメータは考案されたAオブジェクト引数を受け取るためだけに使用されます)。非静的な 'a'の暗黙のオブジェクトパラメータは、あなたのケースでは' A& '型です(constメンバfncsの' A const& ')。 'A :: a()'という呼び出しのオブジェクト引数は両方の暗黙のオブジェクトパラメータにマッチするので、あいまいさがあります。 –

+0

この "考案されたオブジェクトの引数"は* thisと同じ型ですか? – fang

3

名前解決は、コンパイラが行う前に、どのオーバーロードされた関数を使用するかのように発生します。

A::で機能を修飾すると、「Aの内側を見て、aという名前を見つける」ようコンパイラに指示するだけです。あなたが参照している機能を実際に解決するのには役立ちません。

EDIT

だからあなたはA::a()を入力し、最初のコンパイラは「operator()を使用することができますメンバ関数やメンバーのAに見える」と考えています。

その後、コンパイラはここで[OK]を、二つの可能性、1はデフォルトc=0で?a()またはa(int c = 0)と呼ばれている。わからない」、と考えている。

あなたは、静的なキーワードを削除し、obj.a()のような関数を呼び出した場合、まだ曖昧さが存在することになる。

WRT LLVMのパーサ

私はそれが標準で必要とされていないあなたのためにいくつかの余分な作業、になるんだと思いますと仮定するとA::a()は静的です。

+0

誰かが私に答えてくれますか?それは 'static'関数を意味しますか?' static'定義は解決のために名前のmanglingの一部を形成しますか? – Bingo

+0

私は分かりません。しかし、ネームマングリングはリンカーの問題であり、コンパイラーの問題ではありません。 –

+0

アップルのLLVMがそれをうまくコンパイルする理由についての洞察?それは、LLVMのパーサが他の順序で名前解決を行うことを意味しますか? – fang

関連する問題