【问题标题】:cannot access private members in friend ostream无法访问朋友 ostream 中的私人成员
【发布时间】:2015-08-03 00:14:54
【问题描述】:

我尝试结交朋友ostream 功能。编译器说我无法访问该类的私有成员,即使我将其声明为friend。我读了一个类似的问题,它说问题出在namespcaes上。(问题:C++ friend function can't access private members

我的代码如下:

标题:

#include <iostream>
#include <string>
//using namespace std;

namespace biumath
{
#ifndef BIUMATH_H
#define BIUMATH_H
class Assignment
{
private:
    int **m_varArray;
    int m_rowsOfVarArray;
public:
     Assignment(); //1
     Assignment(char symbol, double value); //2
     bool containsValueFor(char symbol) const; //3
     double valueOf(char symbol) const; //4
     void add(char symbol, double val); //5
     friend std::ostream& operator<< (std::ostream& out, 
     const Assignment& assignment);
};
}
#endif

cpp:

#include <iostream>
#include "biumath.h"
using namespace biumath;
using std::cout;
using std::endl;

ostream& operator<< (ostream& out, 
     const Assignment& assignment){
        out<<assignment.m_rowsOfVarArray<<std::endl;
        //return the stream. cout print the stream result.
        return out;
}

【问题讨论】:

  • 包含保护应该在头文件的开头和结尾。

标签: c++ namespaces iostream friend


【解决方案1】:

或者更好的是,通过遵循公共实用程序方法来避免所有不必要的友谊(当您的 Assignment 是多态基类时,这也有好处):

在头文件中:

namespace biumath
{
    class Assignment
    {
    private:
        int **m_varArray;
        int m_rowsOfVarArray;
    public:
        Assignment(); //1
        Assignment(char symbol, double value); //2
        bool containsValueFor(char symbol) const; //3
        double valueOf(char symbol) const; //4
        void add(char symbol, double val); //5
        void write(std::ostream& os) const; // <=== public helper
    };

    // free function overload which defers to helper.
    // NOTE: it's in the biumath namespace so ADL will find it

    inline std::ostream& operator<< (std::ostream& out,
                                       const Assignment& assignment){
        assignment.write(out);
        return out;
    }
}

在 CPP 文件中:

namespace biumath {

    void Assignment::write(std::ostream& os) const {
        os << m_rowsOfVarArray << std::endl;
    }
}

【讨论】:

    【解决方案2】:

    您可以在封闭的命名空间中定义运算符(在您的情况下在全局命名空间中),但您必须使用限定名称。

    这样定义运算符就像

    ostream& biumath::operator<< (ostream& out, 
         const Assignment& assignment){
            out<<assignment.m_rowsOfVarArray<<std::endl;
            //return the stream. cout print the stream result.
            return out;
    }
    

    只有您首先还必须在定义类的同一命名空间中声明运算符。

    如果您希望在全局命名空间中声明该运算符,那么您可以通过以下方式进行操作

    namespace biumath
    {
    class Assignment;
    }
    
    std::ostream& operator<< ( std::ostream &, 
                               const biumath::Assignment & );
    
    
    namespace biumath
    {
    class Assignment
    {
         //...
         friend std::ostream& ::operator<< (std::ostream& out, 
                                            const Assignment& assignment);
    };
    }
    

    【讨论】:

    • 你试过了吗?它仅在之前已在命名空间中声明的情况下才有效,而这里没有。
    • 我的编译器不同意(标准也是如此)。它之前没有在命名空间中声明过(仅作为类的友元),因此无法通过限定查找找到该名称,因此不能将其称为buimath::operator&lt;&lt;。您要么必须在标头中添加声明,要么在命名空间中定义它。
    【解决方案3】:

    您在 biumath 命名空间中与操作员成为朋友,但您没有定义它;而是在全局命名空间中定义一个单独的运算符。

    重新打开源文件中的命名空间,将定义放入其中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-02
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 2020-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多