朋友功能如何运作

时间:2020-01-28 17:54:43

标签: c++ class c++11 operator-overloading friend-function

我想学习如何使用 friend 功能。第一次尝试时,我没什么问题,也不知道如何解决。我遇到以下错误:

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

这是我到目前为止的所有代码:

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

3 个答案:

答案 0 :(得分:1)

撰写时:

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

然后operator+不是成员函数。它是一个自由函数,并且类声明中的行仅声明该函数是类Time的朋友。

作为非成员,二进制文件operator+必须带有2个参数。考虑一下如何使用它:

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

您需要传递ab并返回新的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;
}

您对x有类似的问题,但我不知道该怎么办。如果您了解operator+的问题,那么您也应该可以解决该问题。

答案 1 :(得分:1)

这些错误消息

| 17 |错误:在此范围内未声明“分钟” |

| 18 |错误:未在此范围内声明“小时” |

表示在此函数定义内

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

未声明变量minuteshours。该函数不是该类的成员函数。因此,这些变量不是类Time的对象的数据成员。它们是未声明的标识符。

朋友函数不会像非静态成员类函数那样获取隐式参数this

这些错误消息

| 24 |错误:未在此范围内声明“分钟” |

| 24 |错误:未在此范围内声明“分钟” |

含义相同。函数x不是Time类的成员函数。

如果朋友函数operator +重载了二进制运算符+,则它应具有两个参数。

对于第二个好友函数,似乎它的任务是为Time类型的对象设置值。

应该按照以下演示程序中所示的方式声明和定义friend函数。

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

程序输出为

16:10
10:20
02:30

答案 2 :(得分:0)

friend函数/类是可以访问privateprotected成员的函数/类。

朋友函数不是其声明为朋友的类的成员函数,因此它没有隐式指针this,因此在:

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

因为只要hoursminutes是类型为Time的对象的数据成员,您就需要通过该类的对象来访问它们。

  • 让我们假设您的类Time具有一个名为setMinutes()的成员函数,其定义为:

    int Times::SetMinutes(int h, int m)
    {
           hours = h; // in fact it is translated as: this->hours = h;
           this->minutes = m;
    }
    
  • 您可能已经看到插入运算符<<被类重载为这种方式:

    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;
    } 
    
  • +运算符的声明也不正确:

    friend Time operator+(const Time & t);
    

由于+是二进制运算符,因此它需要两个操作数“ lhs”和“ rhs”,因此您可以:

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

或者:

     Time operator+(const Time & t); // OK
  • 第二个版本有效,因为+是成员函数:这意味着它通过取消引用this和参数来使用运算符称为“ lhs”的对象t为“ rhs”。

  • 首选版本是friend