访问私有类的运营商<<在命名空间(Accessing private class in

2019-11-01 03:42发布

我有一个类Cfoo的带有私人内部类C杆。 我想实施Cfoo的流输出中操作,这又在它的实现使用流输出为C杆。 我能得到这个工作时Cfoo的是在公共的命名空间,但是当我把它放在一个新的命名空间(命名空间foobar的),操作者不再能够访问私有内部类。 我怀疑这是与运营商的完整签名,但我想不通这样的实施编译指定friend声明和实际操作者申报的正确方法。 任何人都可以提出什么我可能会丢失? 需要注意的是,如果流实现在头内嵌做到了编译,但我讨厌揭露执行这样不必要的!

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

Answer 1:

只要将代码放在.cpp文件到命名空间:

namespace foobar {

// your existing code

}


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


Answer 3:

你的operator<< functions现在在foobar命名空间,所以你应该将它们定义为foobar::operator<<



Answer 4:

这个问题可以通过专门的流运算符重载的命名空间来解决:

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的朋友和不能访问其私有成员。



文章来源: Accessing private class in operator<< in namespace