c++友元

类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,而其他函数是无法访问类的私有成员的。但有时这种限制太严格,不适合特定的编程问题。C++提供另一种访问途径-友元。 友元有3种:
●友元函数
●友元成员函数
●友元类
对于一个类而言,它的友元虽然不是该类的成员函数,但是可以访问该类的私有成员。

友元函数

它既可以是一个不属于任何类的普通函数,也可以是另外一个类的成员函数。将一个函数声明为一个类的友元函数后,它可以访问类的私有成员和保护成员。

普通函数作为友元函数

friend 返回值类型 函数名(参数表);

class Date  //日期类
{
private:
    int year; //年
    int month;//月
    int day;//日
public:
    Date(int y, int m, int d) :year(y), month(m), day(d)
    {}
    void show()
    {
        cout << year << "-" << month << "-" << day << endl;
    }
    //声明modifyDate是自己(Date类)的友元,可以访问自己的私有成员
    friend void modifyDate(Date& date, int year, int month, int day);
};

//修改日期的函数,普通函数,不属于任何类
void modifyDate(Date& date, int year, int month, int day)
{   //是Date的友元函数,可以访问date的私有数据
    date.year = year;  
    date.month = month;
    date.day = day;
}

int main()
{
    Date today{2023,8,28};
    today.show();
    modifyDate(today,2023,10,1);
    today.show();

    return 0;
}

说明:在类Date中声明函数modifyDate是自己的友元,那么在modifyDate这个函数中不仅可以访问date的公有成员,也可以访问date的私有成员(当然在这个示例中把该函数定义为类中的函数更好,这里仅仅是介绍友元函数)。

类的成员函数作为友元函数

friend 返回值类型 类名::函数名(参数表);

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

class Time; //类声明

class Date//日期类
{
private:
    int year;
    int month;
    int day;
public:
    Date(int y, int m, int d) :year(y), month(m), day(d)
    {}
    void Calcutetime(const Time &t);//统计当前日期时间(包括日期和时间)是当年第几秒
};

class Time//时间类
{
//没有写访问权限,默认为private
    int hour;
    int minute;
    int second;
public:
    Time(int h, int m, int s) :hour(h), minute(m), second(s)
    {}
    friend void Date::Calcutetime(const Time& t); //友元函数
};

//统计当前日期时间是当年第几秒
void Date::Calcutetime(const Time& t)
{
    int mon[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
    int days = 0;     //天数
    int totaltime = 0;//秒数

    if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)//处理闰年
        mon[1] = 29; //闰年2月29天

    for (int i = 0; i < month - 1; i++)//把前面月份的天数相加
        days += mon[i];

    days += day - 1; //当天还没有过完,不能算,需-1

    //该函数是Time的友元函数,下面可以直接访问t的私有成员
    totaltime = ((days * 24 + t.hour) * 60 + t.minute) * 60 + t.second;

    cout << year << '-' << month << '-' << day << " ";
    cout << t.hour << ':' << t.minute << ':' << t.second << endl;
    cout << "上面的日期时间是当年的第: " << totaltime << " 秒" << endl;
}

int main()
{
    Date date1(2023, 1, 1);
    Time time1(0, 0, 0);
    date1.Calcutetime(time1);

    Date date2(2023, 8, 24);
    Time time2(18, 04, 25);
    date2.Calcutetime(time2);

    return 0;
}

友元类

如果希望A类中的所有成员函数都能够访问B类中所有私有和保护成员,可以将A类中的每个成员函数声明为B类的友元函数,但这样做显得比较烦琐。为此,C++提供了友元类,也就是一个类可以声明为另一个类的友元类。
若在B类中声明A类是其友元类,那么,A类中的任意成员函数都可以访问B类的所有成员。
声明友元类的语句格式为:

friend class 类名;

//友元类
class Date //日期类
{
private:
    int year;
    int month;
    int day;
public:
    Date(int y, int m, int d) :year(y), month(m), day(d)
    {}
    friend class DateFriend; //友元类,DateFriend是自己(Date类)的友元类
};

class DateFriend
{
public:
    void modifyDate(Date& date, int year,int month, int day);//修改日期
    void show(const Date& date);//输出数据
};

void DateFriend::modifyDate(Date& date, int year,int month, int day)
{
    //友元类,可以直接访问date的私有成员
    date.year = year;
    date.month = month;
    date.day = day;
}
void DateFriend::show(const Date& date)
{
    //友元类,可以直接访问date的私有成员
    cout << date.year << "-" << date.month << "-" << date.day << endl;
}

int main()
{
    Date date(2023,8,28);
    DateFriend daf;
    daf.show(date);
    daf.modifyDate(date, 2024,1,1);
    daf.show(date);

    return 0;
}

友元是否有悖于OOP?

乍一看,您可能会认为友元违反了OOP数据隐藏原则,因为友元机制允许非成员函数访问私有数据。然而这个观点太片面了。相反,应将友元函数看做类的扩展接口的组成部分。
请记住,只有类本身可以决定哪一个函数是友元,因此类依然控制了哪些函数可以访问类的私有数据。总之。类方法和友元只是表达类接口的两种不同机制。
友元就是你的好朋友,陌生人可以访问你家客厅,不能访问你的卧室;你的好朋友不仅可以访问你家客厅还能访问你的卧室,这条规则并不会破坏你的私人空间,因为谁是你的好朋友由你决定!

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值