1

現在、C/C++ を使用してソケット プログラミングを行っています。ややクリーンなインターフェイスと、よりオブジェクト指向の構造を使用できるようにするために、C ソケット API の一部の周りにいくつかの単純なラッパー クラスを作成することにしましたが、そうしているうちに問題に遭遇しました。

次のコードがあるとします。

// Global method
int foo(int x)
{
    return x;
}

// Class that calls the global method
class FooBar
{
public:
    void foo() { return; };
    void baz() { foo(1); }
};

g++ は次のエラー メッセージを表示します。

test.cpp: In member function ‘void FooBar::baz()’:
test.cpp:10: error: no matching function for call to ‘FooBar::foo(int)’
test.cpp:9: note: candidates are: void FooBar::foo()

クラスメソッドの名前を変更すると、問題が解決します。

メソッドのシグネチャが異なるにもかかわらず、何らかの名前の競合が発生するのはなぜですか? これを修正する最善の方法は何ですか?

ありがとう/エリック

4

3 に答える 3

8

問題は、最初にクラスのスコープを調べて、foo 関数を見つけることです。ルックアップは停止し、コンパイラは引数の一致を試みます。クラスのそのスコープには foo 関数が 1 つしかないため、関数の呼び出しは失敗します。

free 関数を呼び出したいことを明示的に述べる必要があります。

::foo(1);

別の解決策は、baz 内で関数を宣言することです。

void baz() { int foo(int); foo(1); }

foo 関数が定義されていると想定されるスコープは、クラスの周囲の名前空間です。

于 2008-11-26T13:01:08.120 に答える
3

スコープ解決を使用する必要があります:

::foo(1);

于 2008-11-26T13:00:35.687 に答える
2

解決策は次のとおりです。

void baz() { ::foo(1); }

「メソッドのシグネチャが異なるのに、なんらかの名前の競合があるのはなぜですか?」

C++ は常に、常に最初に名前を検索するためです。関連するスコープで名前が見つかると、そのスコープでその名前に使用できる署名を確認します。したがって、foo()メンバー関数は、foo(int)スコープ内 (つまり、クラスの他のメンバー関数) にある任意の場所で free 関数を非表示にします。

同じ理由で、次のコードはコンパイルされません。

struct A {
    virtual void foo(int) = 0;
    // attempt to provide a useful helper
    virtual void foo() { foo(23); }
};

struct B : public A {
    void foo(int i) {
        std::cout << i << "\n";
    }
};

int main() {
    B b;
    b.foo(); // oops, can't find foo(), because class B hid it
    A &a = b;
    a.foo(); // that works. So much for Liskov's substitution principle.
}

書かれているように、B は基本クラスから機能を削除するため壊れています (ただし、A と呼ばれる場合ではなく、B と呼ばれる場合のみ)。litb は、それを解除する方法を説明する以下のコメントにリンクを提供します。

于 2008-11-26T13:01:51.363 に答える