cannot access private members in friend ostream

2019-01-29 08:24发布

问题:

I tried to make friend ostream function. The compiler say i cannot access private member of the class, even though i declared it as friend. I read a similar question and it say the problem is with the namespcaes.(the question: C++ friend function can't access private members)

My Code is below:

header:

#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;
}

回答1:

or better yet, avoid all unnecessary friendships by deferring to a public utility method (this also has benefits when your Assignment is a polymorphic base class):

in header file:

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

in CPP file:

namespace biumath {

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


回答2:

You may define the operator in the enclosing namespace (in your case in the global namespace) but you have to use the qualified name.

Thus define the operator like

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

Only you also have at first to declare the operator in the same namespace where the class is defined.

If you want that the operator would be declared in the global namespace then you can do it the following way

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


回答3:

You've befriended an operator in your biumath namespace, but you don't define that; instead you define a separate operator in the global namespace.

Re-open the namespace in the source file, and put the definition inside it.