Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在operator中访问私有类<&书信电报;在命名空间中_C++_Namespaces_Operator Overloading_Inner Classes - Fatal编程技术网

C++ 在operator中访问私有类<&书信电报;在命名空间中

C++ 在operator中访问私有类<&书信电报;在命名空间中,c++,namespaces,operator-overloading,inner-classes,C++,Namespaces,Operator Overloading,Inner Classes,我有一个类CFoo和一个私有的内部类CBar。我想为CFoo实现一个stream-output操作符,它反过来在实现中使用CBar的流输出。当CFoo位于公共名称空间中时,我可以实现这一点,但当我将其放置在新名称空间(名称空间foobar)中时,操作符将无法再访问私有内部类。我怀疑这与运算符的完整签名有关,但我无法找到正确的方法来指定友元声明和实际运算符声明,以便编译实现。有人能告诉我可能遗漏了什么吗? 请注意,如果流实现是在头中内联完成的,那么它将被编译,但我讨厌不必要地公开这样的实现 在fo

我有一个类CFoo和一个私有的内部类CBar。我想为CFoo实现一个stream-output操作符,它反过来在实现中使用CBar的流输出。当CFoo位于公共名称空间中时,我可以实现这一点,但当我将其放置在新名称空间(名称空间foobar)中时,操作符将无法再访问私有内部类。我怀疑这与运算符的完整签名有关,但我无法找到正确的方法来指定友元声明和实际运算符声明,以便编译实现。有人能告诉我可能遗漏了什么吗? 请注意,如果流实现是在头中内联完成的,那么它将被编译,但我讨厌不必要地公开这样的实现

在foobar.h中(只需注释掉usefoobarnamespace以测试非命名空间版本):

#定义usefoobarnamespace
#ifdef usefoobarnamespace
名称空间foobar
{
#endif//usefoobarnamespace
类CFoo
{
公众:
CFoo(){}
~CFoo();
void AddBar();
私人:
类CBar
{
公众:
CBar(){m_iVal=++s_iVal;}
国际货币基金组织;
静态整数;
};
std::向量m_aBars;

friend std::ostream&operator您的
operator您的
operator只需将.cpp文件中的代码放入命名空间:

namespace foobar {

// your existing code

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

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

namespace foobar {

// your existing code

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

您需要将运算符定义显式地放在命名空间中。(或使用命名空间完全限定它们)。执行此操作的方式是声明一些,您需要将运算符定义显式地放在命名空间中。(或使用命名空间完全限定它们)。您这样做的方式是声明一些,可以通过专门化命名空间的流运算符重载来解决此问题:

namespace foobar {

// your existing code

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

std::ostream&foobar::operator可以通过专门化命名空间的流运算符重载来解决此问题:

namespace foobar {

// your existing code

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

std::ostream&foobar::operator通常这适用于CFoo操作符,但不适用于CFoo::CBar one。std::ostream&foobar::operator@FlintZA:奇怪,对我有用,我在回答(g++4.3.3)之前编译了它。你能再检查一下吗?顺便说一下,我在你的代码中发现了一个可能的错误,在(*barIter)您可能希望取消引用两次(*(*barIter))为了调用CBar重载运算符。@UncleZiev Well Cougt:)在我的实际代码案例中,内部类对象实际上在映射中,所以我取消引用。其次,在转换为更简单的测试案例时,我错过了这一点。至于此解决方案不编译,我使用Visual Studio 2008编译,所以我认为这是MS c的一个怪癖ompiler不是第一个;)奇怪的是,这对CFoo操作符有效,但对CFoo::CBar one.std::ostream&foobar::operator@FlintZA:奇怪,对我有用,我在回答(g++4.3.3)之前编译了它。你能再检查一下吗?顺便说一下,我在你的代码中发现了一个可能的错误,在(*barIter)中,你可能想取消引用两次(*(*barIter))以便调用CBar重载运算符。@UncleZiev Well-Cougt:)在我实际的代码案例中,内部类对象实际上在一个映射中,所以我正在取消引用。其次,我在转换到更简单的测试用例时错过了这一点。至于这个解决方案,我没有编译,我是用Visual Studio 2008编译的,所以我想这是MS编译器的一个怪癖,不会是第一个;)谢谢,这确实有效。我宁愿不包装cod如果我能帮助的话,我会在名称空间中的实现文件中这样做,但如果我找不到另一个可行的解决方案,我会只为运算符这样做。+1我从来都不明白为什么人们在定义名称空间中的函数/方法时会使用using指令。@FlintZA愿意分享一下这种特殊偏好的原因吗?这是使用名称空间的最简单、最干净的方法。@Neil我们使用的是全番茄(非常好)可视化辅助。它的一个重构工具允许您为函数定义自动创建一个实现。这个自动生成的实现签名包括名称空间,因此使用上述方法需要对代码进行更多的手动修剪。谢谢,这确实有效。我不希望在我的实现中包装代码如果我能帮助的话,我会在名称空间中创建类似这样的文件,但如果我找不到另一个可行的解决方案,我只会为运算符这样做。+1我从来都不明白为什么人们在定义名称空间中的函数/方法时会使用using指令。@FlintZA愿意分享这种特殊偏好的原因吗?这是最简单的,最干净的名称空间使用方式。@Neil我们使用的是全番茄(非常好)可视化辅助。它的一个重构工具允许您自动创建函数定义的实现。此自动生成的实现签名包括名称空间,因此使用上述方法将需要更多的手动修剪代码。我对Niel的回答同上:)我对Niel的回答同上:)