访问运算符<<中的私有类在命名空间中

发布于 2024-08-02 16:51:36 字数 2073 浏览 5 评论 0 原文

我有一个类 CFoo 和一个私有内部类 CBar。我想为 CFoo 实现一个流输出运算符,它又在其实现中使用 CBar 的流输出。当 CFoo 位于公共命名空间中时,我可以使其工作,但是当我将其放置在新命名空间(命名空间 foobar)中时,操作员无法再访问私有内部类。我怀疑这与运算符的完整签名有关,但我无法找出指定友元声明和实际运算符声明的正确方法,以便编译实现。谁能建议我可能缺少什么? 请注意,如果流实现在标头中内联完成,它将会编译,但我讨厌不必要地公开这样的实现!

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

I have a class CFoo with a private inner class CBar. I want to implement a stream ouput operator for CFoo, which in turn uses a stream output for CBar in it's implementation. I can get this working when CFoo is in the common namespace, but when i place it in a new namespace (namespace foobar), the operator can no longer access the private inner class. I suspect this has something to do with the full signature of the operator, but I can't figure out the correct way to specify the friend declaration and the actual operator declaration so the implementation compiles. Can anyone suggest what I might be missing?
Note that it will compile if the stream implementation is done inline in the header, but I hate to expose implementation like this unnecessarily!

in foobar.h (just comment out the usefoobarnamespace to test the non-namespaced version):

#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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

昔梦 2024-08-09 16:51:37

您的操作员<<函数 现在位于 foobar 命名空间中,因此您应该将它们定义为 foobar::operator<<

Your operator<< functions are now in the foobar namespace, so you should define them as foobar::operator<<.

一百个冬季 2024-08-09 16:51:37

该问题可以通过专门为命名空间进行流运算符重载来解决:

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 类的友元,并且无法访问其私有成员。

The issue can be resolved by specializing the stream operator overloading for the 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<<")";
} 

By default, the global definitions of these functions are getting overloaded. They are not friends of class CFoo and cannot access its private members.

妄断弥空 2024-08-09 16:51:36

只需将.cpp文件中的代码放入命名空间即可:

namespace foobar {

// your existing code

}

Simply put the code in the .cpp file into the namespace:

namespace foobar {

// your existing code

}
仅一夜美梦 2024-08-09 16:51:36

您需要将运算符定义显式放入命名空间中。 (或者使用命名空间完全限定它们)。你这样做的方式你声明了一些 <<运算符(位于名称空间 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<<")";
    }
}

You need to put the operator definitions explicitly in a namespace. (Or fully qualify them with the namespace). The way you are doing it you declare some << operators (that are in namespace foobar), then you define some completely new << operators in the global namespace.

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<<")";
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文