accessing private mem w/o friend?

wondering is there a way to access the private members while in overloaded operator without declaring 'friend' ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  istream & operator >>( istream & input, Course & C )
{
  input >> unitName >> unitId >> credits; // how should this part be?
  return input;
}

ostream & operator <<( ostream & os, const Course & C )
{
  os << "  Course:  " << C.getUnitName() << '\n'
     << "  Section: " << C.getUnitId() << '\n'
     << "  Credits: " << C.GetCredits() << '\n';
  return os;
}


ive tried the following:
- searching the net for possible explanation but with no avail.
- using the ifstream to read in the object but other parts of my code gotten the 'no matching operator >>' error
is there a way to access the private members while in overloaded operator without declaring 'friend' ?

yes, by using public getters and setters
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <string>

class Person
{
    private:
    std::string m_name;
    int m_age;

    public:
    Person () {}
    Person (std::string name, int age) : m_name (name), m_age (age) {}
    void setName(const std::string& name){m_name = name;}
    void setAge(const int& age){m_age = age;}
    std::string getName()const {return m_name;}
    int getAge()const {return m_age;}
};
std::istream& operator >> (std::istream& is, Person& p)
{
    std::cout << "Enter name: \n";
    std::string name{};
    getline (is, name);
    p.setName(name);
    std::cout << "Enter age: \n";
    int age{};
    is >> age;
    p.setAge(age);

    return is;
}
std::ostream& operator << (std::ostream& os, const Person& p)
{
    os << "Name: " << p.getName() << " " << "Age: " << p.getAge() << " \n";
    return os;
}

int main()
{
    Person p;
    std::cin >> p;
    std:: cout << p;
}


there are lots of ugly ways to do this. Most of them are bad ideas that are only generally useful if you are stuck using a locked 3rd party library that is hiding things from you. They all generally end up being a version of "acquire a pointer to the offending item".



friending the I/O operators (and, actually, all of binary operators, as long as you also define them inside the class) is really the most appropriate way to define them in C++.
Why look for something else?
Another option is to delegate the IO to public method:
1
2
3
4
5
6
7
8
9
10
11
12
13
class Course {
public:
   istream &read(istream &is) {
      is>> unitName >> unitId >> credits;
      return input;
   }
    ...
};

istream & operator >>( istream & input, Course & C )
{
    return C.read(input);
}


But why add the extra complication when you can just make operator>> a friend?
closed account (48T7M4Gy)
http://en.cppreference.com/w/cpp/language/friend

The first two lines of the entry on friend explain in clear terms what friend is all about. So, as Cubbi says why bother looking for alternatives?
Last edited on
Hi guys, i know that using the 'friend' is the most effective solution for this problem. I think my lecturer is drilling us on using the getters/setters in the class to retrieve private members.
closed account (48T7M4Gy)
@OP Probably sounds like nagging but ... the point is friend is the way for another class to access a classes private members in a controlled and consistent way, consistent with data hiding principles.

It is more or less not consistent with the principles of C++ to use getters and setters even though it can be done albeit by over-complicating a simple method.

Maybe your lecturer doesn't understand what friend is all about.
the point is friend is the way for another class to access a classes private members in a controlled and consistent way, consistent with data hiding principles.

I suspect that the point the prof is trying to make is that you shouldn't provide access to private data unless it's necessary. If there are getter and setter functions available for everything that you need to print, then there's no need to make the << and >> operators friends.

The advantage of this comes when you want to change the private data. The fewer places that have access to it, the fewer places that you have to worry about.

I'll add my usual caveat: it's an interesting and valuable idea, but it adds certain complexity now, for a possible simplification in the future. Before doing it, one should weigh the chances of using the future simplification.
Sometimes (particularly in the case of overloaded binary operations), the non-member function is declared as an inline friend (even if it does not require any access to non-public members of the class). The advantage of doing this is that the function can't be found other than through ADL. This is ideal for overloaded operators (ie. it works as expected when used in as an operator, but it does not pollute the enclosing or associated namespaces, and it does not contribute to potential ambiguities in overload resolution).

AFAIK, this practice is currently limited to expert code; it hasn't entered mainstream C++ as yet.

I think this is what Cubbi meant when he said:
friending the I/O operators (and, actually, all of binary operators, as long as you also define them inside the class) is really the most appropriate way to define them in C++.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
namespace A
{
    struct B
    {
        int value() const { return v ; }
        void value( int new_val ) { v = new_val ; }

        private: int v = 23 ;

        // foo is not visible except through ADL
        friend int foo( B& b, int i ) { b.value( b.value() + i ) ; return b.value() ; }
    };

    // bar pollutes the enclosing namespace
    int bar( B& b, int i ) { b.value( b.value() + i ) ; return b.value() ; }
}

int main()
{
    A::B b ;

    bar( b, 5 ) ; // fine: found via ADL

    A::bar( b, 5 ) ; // fine: bar is a member of namespace A
    auto p = &A::bar ; // fine: bar is a member of namespace A

    foo( b, 5 ) ; // fine: found via ADL

    A::foo( b, 5 ) ; // *** error: foo is not a member of namespace A
    auto p2 = &A::foo ; // *** error: foo is not a member of namespace A
    auto p3 = &A::B::foo ; // *** error: foo is not a member of A::B
    auto p4 = &::foo ; // *** error: foo is not a member of the global namespace
    // foo can be accessed only via ADL (aka koenig lookup).
}

http://coliru.stacked-crooked.com/a/5e4557bbd05609ae
closed account (48T7M4Gy)
Bingo!
friend declaration
C++
C++ language
Classes
The friend declaration appears in a class body and grants a function or another class access to private and protected members of the class where the friend declaration appears.
closed account (48T7M4Gy)
http://stackoverflow.com/questions/35904143/friend-not-allowed-outside-of-a-class-definition
> The friend declaration appears in a class body

The point was not about the friend declaration being in the body of he class; that the friend declaration must appear in the body of the class is a syntanctic requirement.

The discussion is about the distinction between placing the definition of the friend function within the body of the class vs. placing it outside the body of the class.
closed account (48T7M4Gy)
Exactly, just as I have been doing. I'm not familiar with syntanctic requirements though. I suppose they are in the C++ expert scheme of things.
Last edited on
It is embarrassingly simple:

It is required that the declaration of a friend must be inside the class body.
If it appears outside the class body, it is a syntax error.

It is not required that the definition of a friend function must appear inside the class body.
The definitions of a friend function can be outside the class body in a well-formed program.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>

struct B ;

struct A
{
    explicit A( int v ) : v(v) {}
    int value() const { return v ; }

    private: int v ;

    // friend declaration for operator+
    // it is required that this declarations must appear within the body of he class
    friend A operator+ ( A a1, A a2 ) ;

    // friend declaration for operator-
    // again, it is required that this declarations must appear within the body of the class
    // however, for operator-, the definition also appears in the body of he class
    friend A operator- ( A a1, A a2 ) { return A{ a1.value() - a2.value() } ; }
};

// there is no requirement that the definition of a friend must appear within the body of the class
A operator+ ( A a1, A a2 ) { return A{ a1.value() + a2.value() } ; }

int main()
{
    const A a1(22), a2(35) ;
    const auto a3 = a1 + a2 ;
    const auto a4 = a1 - a2 ; // operator- is found via adl
    std::cout << a3.value() << ' ' << a4.value() << '\n' ; // 57 -13
 }

http://coliru.stacked-crooked.com/a/4048c869202bbc2b
Topic archived. No new replies allowed.