1 static
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化
静态定义的成员变量在类外定义,变量类型 类名::变量名=value的形式。
此外,static还可以在类里面定义函数,这种static修饰的函数在外调用必须加域名才能使用,因为static修饰的函数不会隐含this指针。
2 友元
友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多
用。
友元分为:友元函数和友元类
2.1 友元函数
通过实现重载operator<<去理解友元函数
在之前定义的日期类时,我们实例化日期对象然后去打印日期类的年月日定义了打印函数
我们可以这样去实现日期对象成员变量的值打印,但我们是否能利用重载实现通过cout<<的形式将的内容打印出来呢?
这时候我们就需要去定义一个重载函数operator<<。
这样我们就能在主函数去调用重载函数实现打印,其实d1.operator<<(cout)其实等价于d1<<cout。
但是,这样不是很方便也不符合我们常规写法,我们希望的写法是cout<<d1。
由于类里面定义的函数默认都有一个Data *this的指针参数,在外调用的时候都会将对象的地址传入,例如d1.operator(cout)==d1.operator(&d1,cout)。这个顺序是编译器默认的,不允许修改或者交换的,要达到cout<<d1的想法我们无法实现cout.operator<<(&d1),所以我们只能让它不为我们默认传入参数,我们自己定义传入参数,这时就需要用到static去实现。
所以我们的代码就变成了这样:
把函数定义在类外,不让编译器帮我我们默认添加一个Date*this的参数,并且我们自己加入Date*d,并且放到ostream&_cout的后面,但这时由于权限的问题,类外无法访问类内的成员变量,所以我们需要通过友元friend声明一下。
这样就能实现cout<<d1的效果了。
但这只能实现cout<<d1的效果,那如果想要实现cout<<d1<<d2<<endl的效果呢,这时就需要将函数稍微修改一下。
这样就能达到每次输出之和都会返回一个cout去输出下一个。
总结
因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。所以要将operator<<重载成全局函数。但又会导致类外没办法访问成员,此时就需要友元来解决。operator>>同理。
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。
说明:
友元函数可访问类的私有和保护成员,但不是类的成员函数
友元函数不能用const修饰
友元函数可以在类定义的任何地方声明,不受类访问限定符限制
一个函数可以是多个类的友元函数
友元函数的调用与普通函数的调用原理相同
2.2 友元类
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
标签:友元,函数,--,成员,定义,static,cout From: https://blog.csdn.net/m0_63703622/article/details/142025648友元关系是单向的,不具有交换性。
比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
友元关系不能传递如果B是A的友元,C是B的友元,则不能说明C时A的友元。
友元关系不能继承。