Arteniks
Arteniks

Reputation: 13

How friend function works

I wanted to learn how to use friend functions. When attempting it for the first time, I have little problem and I don't know how to fix it. I got the following errors:

|17|error: 'minutes' was not declared in this scope|
|18|error: 'hours' was not declared in this scope|
|24|error: 'minutes' was not declared in this scope|
|24|error: 'minutes' was not declared in this scope|

Here's is all the code I have as of now:

#include <iostream>
using namespace std;

class Time
{

    int hours;
    int minutes;
    friend Time operator+(const Time & t);
    friend void x(Time h, Time m );

};

Time operator+(const Time & t)
{
    Time sum;
    sum.minutes = minutes + t.minutes;
    sum.hours = hours + t.hours + sum.minutes / 60;
    sum.minutes %= 60;
    return sum;
}


void x(Time h, Time m) {hours = h; minutes = m;}

Upvotes: 1

Views: 213

Answers (3)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122350

When you write:

class Time
{
    friend Time operator+(const Time & t);
};

Then operator+ is not a member function. It is a free function and the line in the class declaration only declares that this function is a friend of the class Time.

As a non-member, the binary operator+ has to take 2 parameters. Consider how you would use it:

Time a,b;
Time c = a + b;

You need to pass a and b and return a new Time c:

Time operator+(const Time & t1,const Time& t2)
{
    Time sum;
    sum.minutes = t1.minutes + t2.minutes;
    sum.hours = t1.hours + t2.hours + sum.minutes / 60;
    sum.minutes %= 60;
    return sum;
}

You have similar problem with x, but I don't understand what it is supposed to do. If you understand the issue with operator+ you should also be able to fix that.

Upvotes: 1

Maestro
Maestro

Reputation: 2552

friend functions/classes are functions/classes that can access private and protected members.

A friend function is not a member function f the class it is declared friend of so it doesn't have the implicit pointer this so in:

void x(Time h, Time m) {hours = h; minutes = m;} // doesn't compile

Because as long as hours and minutes are data members of an object of type class Time you need to access them via an object of that class.

  • let' assume your class Time has a member function named setMinutes() which is defined as:

    int Times::SetMinutes(int h, int m)
    {
           hours = h; // in fact it is translated as: this->hours = h;
           this->minutes = m;
    }
    
  • As you may have seen the insertion operator << be overloaded by a class this way:

    friend std:ostream& operator<<(std::ostream& out, const Time& rhs) // friend here is only to access private and protected members
    {
            out << rhs.hours << " " << rhs.minutes; // not out << hours << minutes;   * if the keyword `friend` is removed then this line will not compile: "accessing private members".
            return out;
    } 
    
  • Also the declaration of + operator is incorrect:

    friend Time operator+(const Time & t);
    

Because + is a binary operator thus it needs two operands "lhs" and "rhs" so you can:

     friend Time operator+(const Time & lsh, const Time& rhs);

Or:

     Time operator+(const Time & t); // OK
  • The second version works because the + is a member function: which means it uses the object on which the operator called as the "lhs" through de-referencing this and the argument t as "rhs".

  • The preferred version is the friend one.

Upvotes: 0

Vlad from Moscow
Vlad from Moscow

Reputation: 310960

These error messages

|17|error: 'minutes' was not declared in this scope|

|18|error: 'hours' was not declared in this scope|

means that within this function definition

Time operator+(const Time & t)
{
    Time sum;
    sum.minutes = minutes + t.minutes;
                  ^^^^^^^
    sum.hours = hours + t.hours + sum.minutes / 60;
                ^^^^^
    sum.minutes %= 60;
    return sum;
}

the variables minutes and hours are not declared. The function is not a member function of the class. So these variables are not data members of an object of the class Time. They are undeclared identifiers.

Friend functions do not get the implicit argument this as non-static member class functions do.

These error messages

|24|error: 'minutes' was not declared in this scope|

|24|error: 'minutes' was not declared in this scope|

have the same meaning. The function x is not a member function of the class Time.

If the friend function operator + overloads the binary operator + then it shall have two parameters.

As for the second friend function then it seems its task is to set values for an object of the type Time.

The friend functions should be declared and defined the following way as it is shown in the demonstrative program below.

#include <iostream>
#include <iomanip>

class Time
{
    int hours;
    int minutes;
    friend Time operator +( const Time &t1, const Time &t2 );
    friend void x( Time &t, int h, int m );
    friend std::ostream & operator <<( std::ostream &is, const Time &t );
};

Time operator +( const Time &t1, const Time &t2 )
{
    const int HOURS_IN_DAY = 24;
    const int MINUTES_IN_HOUR = 60;

    Time t;

    t.hours  = t1.hours + t2.hours + ( t1.minutes + t2.minutes ) / MINUTES_IN_HOUR;
    t.hours %= HOURS_IN_DAY;
    t.minutes = ( t1.minutes + t2.minutes ) % MINUTES_IN_HOUR;

    return t;
}

void x( Time &t, int h, int m )
{
    t.hours = h;
    t.minutes = m;
}

std::ostream & operator <<( std::ostream &os, const Time &t )
{
    return 
    os << std::setw( 2 ) << std::setfill( '0' ) << t.hours 
       << ':'
       << std::setw( 2 ) << std::setfill( '0' ) << t.minutes; 
}

int main() 
{
    Time t1;

    x( t1, 16, 10 );

    std::cout << t1 << '\n';

    Time t2;

    x( t2, 10, 20 );

    std::cout << t2 << '\n';

    std::cout << t1 + t2 << '\n';

    return 0;
}

The program output is

16:10
10:20
02:30

Upvotes: 2

Related Questions