Pergunta

Eu tenho um CFoo classe com uma classe interna privada CBar. Eu quero implementar um operador de fluxo de ouput para CFoo, que por sua vez utiliza uma saída de fluxo para CBar na sua implementação. Eu posso começar este trabalho quando CFoo está no namespace comum, mas quando eu colocá-lo em um novo namespace (foobar namespace), acesso a operadora não pode mais a classe interna privada. Eu suspeito que isso tem algo a ver com a assinatura definitiva do operador, mas eu não consigo descobrir a maneira correta de especificar a declaração amigo e a declaração do operador real para que as compilações de implementação. Alguém pode sugerir que eu poderia estar faltando? Note que irá compilação se a implementação corrente é feito em linha no cabeçalho, mas eu odeio para expor implementação como esta desnecessariamente!

em blabla.h (apenas comentar o usefoobarnamespace para testar a versão não namespaced):

#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

e em 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<<")";
}
Foi útil?

Solução

Basta colocar o código no arquivo .cpp no ??espaço de nomes:

namespace foobar {

// your existing code

}

Outras dicas

Você precisa colocar as definições de operador explicitamente em um namespace. (Ou totalmente qualificá-los com o namespace). A maneira como você está fazendo isso você declarar algumas << operadores (que estão em foobar namespace), então você definir alguns completamente novos << operadores no espaço de nomes global.

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<<")";
    }
}

Seu operator<< functions estão agora no namespace foobar, então você deve defini-los como foobar::operator<<.

O problema pode ser resolvido através da especialização do operador fluxo de sobrecarga para o namespace:

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<<")";
} 

Por padrão, as definições globais destas funções estão ficando sobrecarregado. Eles não são amigos de CFoo classe e não pode acessar seus membros privados.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top