C++基础——友元函数和内部类讲解

      目录    

一.友元:

        友元函数:

友元类

二.内部类

1.定义:

2.内部类的另一个特点:


一.友元:

        友元函数:

        友元为类外的函数提供了一种突破封装的方式,简单来说就是让类外能够破解private、protected型私有类型成员变量或函数,为其提供了便利。之前在讲流提取、流插入运算符函数重载的时候简单介绍了一下友元,大家可以来看一看这篇博客中,类外是如何能够调用重载函数的。C++基础——流插入提取运算符重载函数_

class Date
{	
	
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout << d._year << "-" << d._month << "-" << d._day;
	return _cout;
}
istream& operator>>(istream& _cin, Date& d)
{
	_cin >> d._year;
	_cin >> d._month;
	_cin >> d._day;
	return _cin;
}
int main()
{
	Date d;
	cin >> d;
	cout << d << endl;
	return 0;
}

        流插入和流提取运算符想要在类外进行运算符的重载,需要用到友元,让这两个函数在类内发布友元声明,这样类外就可以将其视为朋友,轻而易举的访问到Date类的非公有成员了。

友元类

        假设类A想要访问类B的非公有成员,就需要在类B中存放类A的友元声明了,也是friend关键字+class+类名即可。

        

class Time{
	friend class Date;   // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类
	                    //中的私有成员变量
public:
	Time(int hour = 0, int minute = 0, int second = 0)
		: _hour(hour)
		, _minute(minute)
		, _second(second)
	{}
private:
	int _hour;
	int _minute;
	int _second;
};
class Date{
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
	void SetTimeOfDate(int hour, int minute, int second){
		// 直接访问时间类私有的成员变量
		_t._hour = hour;
		_t._minute = minute;
		_t._second = second;
	}
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};

将Time类外的Date类在Time类内加上friend, Time类会视Date类为朋友,Date类可以访问Time类的私有成员,Date可以偷Time的家,而Time类不是Date的朋友,Time类不可以访问Date的私有成员。而在SetTimeOfDate函数中,成员变量_t就可以直接访问到Time类的非公有成员。 

        

        需要注意的是:使用友元会增加耦合度,破坏了封装,所以友元不宜多用。

 

二.内部类

1.定义:

        将一个类定义在另一个类的内部,内部类是一个独立的类,它不属于外部类,更不能通过外部类去访问内部类成员。

示例代码,如下:

class A
{
private:
    static int k;
    int h;
public:
    class B             // B天生就是A的友元,类B可以访问类A的成员,但类A不能访问类B的成员
    {
    public:
        void foo(const A& a)
        {
            cout << k << endl;  //OK
            cout << a.h << endl;//OK
        }
    private:
        double _b;
        int _a;
    };
};

int A::k = 1;

int main()
{
    A aa;      
    cout << sizeof(A) << endl;
    cout << sizeof(aa) << endl;   

    cout << sizeof(A::B) << endl;   //16字节


    A::B b;
    b.foo(A());

    return 0;
}

        由定义得,内部类不属于外部类,所以我写了两行行检测类A,类A对象存储大小的代码,发现:

        结果都为4字节,即只存储了int h的大小,且静态成员变量在静态区,所以不进内存空间,那么类B中的a,b成员完全没有算进去。所以由此推断:这个内部类等价于是两个独立的类 。

        但是若类B想要创建对象还是得通过类A才可以,毕竟类B在类A的内部        ~哈哈哈,没办法!

2.内部类的另一个特点:

        内部类天生就是是外部类的友元,也就是说,不需要在类A中发表类B的友元声明,类B也可以随意的访问类A的非公有成员!!!

         

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙予清的zzz~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值