16

グローバル名前空間で二項演算子を定義したいと思います。オペレーターは、別の名前空間で定義されているクラスで動作し、オペレーターはそのクラスのプライベート メンバーにアクセスする必要があります。私が抱えている問題は、クラス定義でグローバル演算子をフレンドにするときに、そのグローバル演算子をスコープする方法がわからないことです。

私は次のようなものを試しました:

namespace NAME
{
    class A {
        public:
            friend A ::operator * (double lhs, const A& rhs);
        private:
            int private_var;
    };
}

A operator * (double lhs, const A& rhs)
{
    double x = rhs.private_var;
    ...
}

コンパイラ (g++ 4.4) は、それをどう処理するかを知りませんでした。ラインのようです

friend A ::operator * ()

(疑似コード)のようなものとして評価されます

(A::operator)

それ以外の

(A) (::operator)

演算子の宣言で :: を省略した場合、コンパイルは機能しますが、演算子は名前空間 NAME にあり、グローバル名前空間にはありません。

このような状況でグローバル名前空間を修飾するにはどうすればよいですか?

4

4 に答える 4

17

まず、演算子の宣言に A の名前空間修飾がないことに注意してください。

NAME::A operator * (double lhs, const NAME::A& rhs)

そして、決定的なトリックは、「疑似コード」で提案したように、このようにフレンド宣言に括弧を追加することです

friend A (::operator *) (double lhs, const A& rhs);

すべてをコンパイルするには、いくつかの前方宣言が必要で、次のようになります。

namespace NAME
{
    class A;
}

NAME::A operator * (double lhs, const NAME::A& rhs);

namespace NAME
{
    class A {
        public:
            friend A (::operator *) (double lhs, const A& rhs);
        private:
            int private_var;
    };
}

NAME::A operator * (double lhs, const NAME::A& rhs)
{
    double x = rhs.private_var;
}

ただし、アレクサンダーは正しいです。おそらく、パラメーターと同じ名前空間でオペレーターを宣言する必要があります。

于 2010-02-05T13:17:09.017 に答える
5

これはコンパイルされます。これも機能することをテストせずに想定しています。括弧の使用に注意してください。

namespace NAME {class A; }
NAME::A operator * (double lhs, const NAME::A& rhs);

namespace NAME
{
    class A {
        public:
            friend A (::operator *) (double lhs, const A& rhs);
        private:
            int private_var;
    };
}

NAME::A operator * (double lhs, const NAME::A& rhs)
{
    double x = rhs.private_var;
    return rhs;
}

int main() {}

ただし、アレクサンダーが言及しているように、あなたの質問では、オペレーターが名前空間 NAME にない理由が説明されていません。どちらの方法でも、として呼び出すことができます1.0 * some_A_instance。そのため、自分自身に不必要なトラブルを引き起こしている可能性があります。

于 2010-02-05T13:12:44.183 に答える
3

可能です - 宣言子を括弧で囲むことができます:friend A (::operator * (double lhs, const A& rhs));

また、クラスと関数の両方を前方宣言する必要があります。

namespace NAME {class A;}
NAME::A operator *(double lhs, const NAME::A& rhs);

// ...

namespace NAME
{
    class A {
        public:
            friend A (::operator * (double lhs, const A& rhs));
        private:
            int private_var;
    };
}

NAME::A operator *(double lhs, const NAME::A& rhs) {
  //...
}

しかし、可能であれば両方を同じ名前空間で定義する方がよいという Andreas の意見に同意します。

于 2010-02-05T13:13:23.730 に答える
3

あなたの質問に対する正確な答えはわかりません。

しかし、パラメーターの名前空間の外でオペレーターを定義するのは非常に悪い考えです (今では、オペレーターにとって非常に便利な引数依存のルックアップをカットしています)。

于 2010-02-05T13:01:16.677 に答える