0

プライベート内部クラス CBar を持つクラス CFoo があります。CFoo のストリーム出力演算子を実装したいと思います。これは、その実装で CBar のストリーム出力を使用します。CFoo が共通の名前空間にある場合はこれを機能させることができますが、新しい名前空間 (名前空間 foobar) に配置すると、オペレーターはプライベート内部クラスにアクセスできなくなります。これは演算子の完全な署名と関係があると思われますが、実装がコンパイルされるようにフレンド宣言と実際の演算子宣言を指定する正しい方法がわかりません。誰かが私が見逃している可能性があるものを提案できますか? ストリームの実装がヘッダーでインラインで行われている場合はコンパイルされることに注意してください。ただし、このような実装を不必要に公開するのは嫌いです。

foob​​ar.h で (usefoobarnamespace をコメントアウトして、名前空間のないバージョンをテストします):

#define usefoobarnamespace
#ifdef usefoobarnamespace
namespace foobar
{
#endif // usefoobarnamespace
    class CFoo
    {
    public:
        CFoo() {}
        ~CFoo();
        void AddBar();
    private:
        class CBar
        {
        public:
            CBar() {m_iVal = ++s_iVal;}
            int m_iVal;
            static int s_iVal;
        };

        std::vector<CBar*> m_aBars;

        friend std::ostream& operator<<(std::ostream& rcStream, CFoo& rcFoo);
        friend std::ostream& operator<<(std::ostream& rcStream, CFoo::CBar& rcBar);
    };
    std::ostream& operator<<(std::ostream& rcStream, CFoo& rcFoo);
    std::ostream& operator<<(std::ostream& rcStream, CFoo::CBar& rcBar);
#ifdef usefoobarnamespace
}
#endif // usefoobarnamespace

そしてfoobar.cppで:

#ifdef usefoobarnamespace
using namespace foobar;
#endif // usefoobarnamespace

int CFoo::CBar::s_iVal = 0;


CFoo::~CFoo()
{
    std::vector<CBar*>::iterator barIter;
    for (barIter = m_aBars.begin(); barIter != m_aBars.end(); ++barIter)
    {
        delete (*barIter);
    }
}

void CFoo::AddBar()
{
    m_aBars.push_back(new CBar());
}


std::ostream& operator<<( std::ostream& rcStream, CFoo& rcFoo )
{
    rcStream<<"CFoo(";
    std::vector<CFoo::CBar*>::iterator barIter;
    for (barIter = rcFoo.m_aBars.begin(); barIter != rcFoo.m_aBars.end(); ++barIter)
    {
        rcStream<<(*barIter);   
    }
    return rcStream<<")";
}

std::ostream& operator<<( std::ostream& rcStream, CFoo::CBar& rcBar )
{
    return rcStream<<"CBar("<<rcBar.m_iVal<<")";
}
4

4 に答える 4

2

.cpp ファイルのコードを名前空間に配置するだけです。

namespace foobar {

// your existing code

}
于 2009-08-21T09:29:57.413 に答える
2

オペレーター定義を名前空間に明示的に配置する必要があります。(または、名前空間で完全に修飾します)。あなたがやっている方法では、いくつかの << 演算子 (名前空間 foobar にあります) を宣言してから、グローバル名前空間でいくつかの完全に新しい << 演算子を定義します。

namespace foobar
{
    std::ostream& operator<<( std::ostream& rcStream, CFoo& rcFoo )
    {
        rcStream<<"CFoo(";
        std::vector<CFoo::CBar*>::iterator barIter;
        for (barIter = rcFoo.m_aBars.begin(); barIter != rcFoo.m_aBars.end(); ++barIter)
        {
            rcStream<<(*barIter);   
        }
        return rcStream<<")";
    }

    std::ostream& operator<<( std::ostream& rcStream, CFoo::CBar& rcBar )
    {
        return rcStream<<"CBar("<<rcBar.m_iVal<<")";
    }
}
于 2009-08-21T09:30:24.447 に答える
1

あなたoperator<< functionsは今foobar名前空間にいるので、それらを として定義する必要がありますfoobar::operator<<

于 2009-08-21T09:29:32.360 に答える
0

この問題は、ストリーム演算子のオーバーロードを名前空間に特化することで解決できます。

std::ostream& foobar::operator<<( std::ostream& rcStream, CFoo& rcFoo )
{
    rcStream<<"CFoo(";
    std::vector<CFoo::CBar*>::iterator barIter;
    for (barIter = rcFoo.m_aBars.begin(); barIter != rcFoo.m_aBars.end(); ++barIter)
    {
        rcStream<<(*barIter);   
    }
    return rcStream<<")";
}

std::ostream& foobar::operator<<( std::ostream& rcStream, CFoo::CBar& rcBar )
{
    return rcStream<<"CBar("<<rcBar.m_iVal<<")";
} 

デフォルトでは、これらの関数のグローバル定義はオーバーロードされています。それらはクラス CFoo のフレンドではなく、そのプライベート メンバーにアクセスできません。

于 2009-08-21T09:41:51.803 に答える