C++中的友元函数和友元类

本文介绍了友元函数和友元类的概念,如何通过友元提高程序运行效率,以及它们如何打破类的封装性。通过案例分析了operator<<和operator>>的重载问题,展示了友元在访问私有成员的应用。
摘要由CSDN通过智能技术生成

零、声明

本文转载自链接:本文链接:https://blog.csdn.net/Jacky_Feng/article/details/109533248,对于其中部分内容有所修改,侵删。

一、友元函数

结合着类的特性,可知:类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性。另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。

为了解决上述问题,提出一种使用友元的方案。友元是一种定义在类外部的普通函数,但它需要在类体内进行声明,为了与该类的成员函数加以区别,在声明时前面加以关键字friend。友元不是成员函数,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。

1.1 案例分析

问题:现在我们尝试去重载operator<<,然后发现我们没办法将operator<<重载成成员函数。因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。所以我们要将operator<<重载成全局函数。但是这样的话,又会导致类外没办法访问成员,那么这里就需要友元来解决。operator>>同理。

#include <iostream>
#include <stdio.h>

using namespace std;

class Date {
  friend ostream &operator<<(ostream &_cout, Date &d);
  friend istream &operator>>(istream &_cin, Date &d);

private:
  int _year;
  int _month;
  int _day;
};

ostream &operator<<(ostream &_cout, Date &d) {
  _cout << d._year << "-" << d._month << "-" << d._day;
  return _cout;
}

istream &operator>>(istream &_cin, Date &d) {
  string s;
  _cin >> s;
  sscanf(s.c_str(), "%d-%d-%d", &d._year, &d._month, &d._day);
  return _cin;
}

int main(int argc, char *argv[]) {
  Date d;
  cin >> d;
  cout << d << endl;
  return 0;
}

1.2 说明

  • 友元函数可访问类的私有成员,但不是类的成员函数
  • 友元函数不能用const修饰
  • 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
  • 一个函数可以是多个类的友元函数
  • 友元函数的调用与普通函数的调用和原理相同

二、友元类

友元除了友元函数以外,友元还可以是类——友元类,即一个类可以作另一个类的友元。当一个类作为另一个类的友元时,这就意味着这个类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的非公有成员。

特性:

  • 友元关系是单向的,不具有交换性。
    比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。

  • 友元关系不能传递
    如果B是A的友元,C是B的友元,则不能说明C时A的友元。

  • 友元关系不能被继承,但对已有的方法来说访问权限不改变。

class Date;

class Time {
  friend class Date;

private:
  int _hour;
  int _minute;
  int _second;
};

class Date {
public:
  void SetTimeofDate(int hour, int minute, int second) {
    _time._hour = hour;
    _time._minute = minute;
    _time._second = second;
  }

private:
  int _year;
  int _month;
  int _day;
  Time _time;
};

三、优缺点

利用friend修饰符,可以让一些普通函数 或 另一个类的成员函数 直接对某个类的保护成员和私有成员进行操作,提高了程序的运行效率;同时避免把类的成员都声明为public,最大限度地保护数据成员的安全。

但是,即使是最大限度地保护数据成员,友元也破坏了类的封装性。

参考

  1. 友元函数和友元类
  2. c++输入和输出重载
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值