2

なぜこれが機能するのですか:

#include "iostream"

class Something {
private:
    static int s_nIDGenerator;
    int m_nID;
    friend int main();
public:
     Something() { m_nID = s_nIDGenerator++; }
     int GetID() const { return m_nID; }
};

int Something::s_nIDGenerator;

int main() {
    Something::s_nIDGenerator = 1;

    Something cFirst;
    Something cSecond;
    Something cThird;

    using namespace std;
    cout << cFirst.GetID() << endl;
    cout << cSecond.GetID() << endl;
    cout << cThird.GetID() << endl;
    return 0;
}

それは印刷します:

1
2
3

そして、これは失敗します:

#include "iostream"

namespace test {   
    class Something {
    private:
            static int s_nIDGenerator;
            int m_nID;
            friend int main();
    public:
            Something() { m_nID = s_nIDGenerator++; }
            int GetID() const { return m_nID; }
    };
};

int test::Something::s_nIDGenerator;

int main() {
    using namespace test;
    Something::s_nIDGenerator = 1;
    // or test::Something::s_nIDGenerator = 1;  same effect if not using using.

    Something cFirst;
    Something cSecond;
    Something cThird;

    using namespace std;
    cout << cFirst.GetID() << endl;
    cout << cSecond.GetID() << endl;
    cout << cThird.GetID() << endl;
    return 0;
}

次のコンパイラ エラー メッセージが表示されます。

**** Internal Builder is used for build               ****
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o src\tuttest1.o ..\src\tuttest1.cpp
..\src\tuttest1.cpp: In function 'int main()':
..\src\tuttest1.cpp:23:5: error: 'int test::Something::s_nIDGenerator' is private
..\src\tuttest1.cpp:27:13: error: within this context
Build error occurred, build is stopped
Time consumed: 161  ms. 

名前空間テストを使用して 2 番目の例を機能させるにはどうすればよいですか?

オブジェクトの周りの名前空間宣言が静的メンバーフォームへのアクセスを妨げているのはなぜですか?


@zmo への私のコメントによると、彼の手がかりに基づいて作業する必要があるのは次のとおりです。

(コメントにはこれのためのスペースやフォーマットがありません。これを回答に設定できなかったため、編集する必要がありました....(どんなにかかったとしても。)

#include "iostream"

namespace test {
    class Something {
    private:
        static int s_nIDGenerator;
        int m_nID;
        friend void load(int);
    public:
        Something() { m_nID = s_nIDGenerator++; }
        int GetID() const { return m_nID; }
    };

    int Something::s_nIDGenerator;

    void load (int value) {
       Something::s_nIDGenerator = value;
    } 

};

int main() {
    using namespace test;
    load (1);

    Something cFirst;
    Something cSecond;
    Something cThird;

    using namespace std;
    cout << cFirst.GetID() << endl;
    cout << cSecond.GetID() << endl;
    cout << cThird.GetID() << endl;
    return 0;
}

「静的メンバーがクラスにあり、名前空間が機能していないのはどうしたの?」については、まだ少し緩いです。これどうしたの?なぜうまくいかなかっtest::Something::s_nIDGeneratorたのですか?(まだ私の最初の質問の一部です。)つまり、これまでのところ、半分答えられています。

なぜこれがうまくいかなかったのか知りたいので、二度とこのレーキに足を踏み入れません。

4

2 に答える 2

3

おそらく、実際の関数が名前空間にないfriend int main()のに、名前空間にも自由な関数があることを宣言が宣言しているためです。main()main()

それを修正するには?最初に のint main();前 (および外側)に宣言しnamespace test、次にそれfriend int ::main()がグローバル名前空間にあることを示します。

詳細については、この質問を参照してください。

于 2012-05-20T14:00:43.350 に答える
1

まあ、あなたの質問のようにすることは決してお勧めしませんが、コードを「そのまま」機能させる方法は次のとおりです。

#include <iostream>

int main(); // declare main beforehands so it can be seen by Something

namespace test {   
    class Something {
    private:
            static int s_nIDGenerator;
            int m_nID;
            friend int ::main(); // take the main from global namespace
    public:
            Something() { m_nID = s_nIDGenerator++; }
            int GetID() const { return m_nID; }
    };
};

int test::Something::s_nIDGenerator;

int main() {
    using namespace test;
    Something::s_nIDGenerator = 1; // tada that works

    Something cFirst;
    Something cSecond;
    Something cThird;

    using namespace std;
    cout << cFirst.GetID() << endl;
    cout << cSecond.GetID() << endl;
    cout << cThird.GetID() << endl;
    return 0;
}

しかし、これはフレンド関数の間違った使用例です。私が提案した解決策(クラスSomething内で関数を使用する)は、読みやすさと理解の点ではるかに優れています。

于 2012-05-20T14:41:13.697 に答える