浅谈友元和static成员
前言
在说这两个之前,我们再掰扯一下构造函数,之前我们在“浅谈六个成员函数”中提到了参数列表初始化。
又叫“初始化列表”。
用法:以冒号开始,接着是逗号分隔的数据成员列表,每个成员变量后面跟着放在括号中的初始值或表达式。
注:
1.每个成员变量在初始化列表中只能出现一次;
2.类中若包含:引用成员变量、const成员变量、自定义类型成员,则必须使用初始化列表进行初始化;
3.成员变量在类中的声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。
提示:以下是本篇文章正文内容
一、友元
在大学生活中,我们经常要交一些实验报告,这使我们很头疼,基本上每个宿舍都会有“那个男人”站出来写报告,然后其他人把报告改个学号姓名上交。友元就相当于这些白piao的舍友一样。
友元分为:友元函数和友元类
友元提供了一种突破封装的方式,有时提供了便利,但是友元会增加耦合度,这不符合我们的“高内聚,低耦合”的思想,破坏了封装,所以友元不宜多用。
1.友元函数
例如当我们想重载“<<”或“>>”时,发现我们无法将operator<<重载成成员函数,因为cout输出流对象和成员函数隐含的this指针在抢占第一个参数的位置,this指针默认是第一个参数也就是“<<”的左操作数,但是实际使用中cout需要是第一个形参对象,才能正常使用。因此我们只能将operator<<重载为非成员函数,比如全局函数,但是这样的话又不能访问成员变量。友元函数便可以完美解决这个问题。
class Date
{
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);
public:
Date(int year, int month, int day) :m_year(year), m_month(month), m_day(day)
{}
private:
int m_year;
int m_month;
int m_day;
};
ostream& operator<<(ostream& out, const Date& d)//以引用返回可以连续输出
{
out << d.m_year << "-" << d.m_month << "-" << d.m_day;
return out;
}
istream& operator>>(istream& in, Date& d)
{
in >> d.m_year;
in >> d.m_month;
in >> d.m_day;
return in;
}
友元函数可以直接访问类的私有成员,它不属于任何类,需要在类里面用friend关键字声明。
特征:
1.友元函数可访问类的私有和保护成员,但不是类的成员函数;
2.友元函数不能用const修饰;
3.友元函数可以在类定义的任何地方声明,不受类访问限定符限制;
4.一个函数可以是多个类的友元函数;
5.友元函数的调用与普通函数调用原理相同。
2.友元类
和友元函数意义差不多,友元类的所有成员函数都可以是另一个类的友元函数,都可以访问类一个类的私有成员。
class Time
{
friend class Date;//代表Date类是Time的友元类。
public:
Time(int hour = 0, int minute = 0, int second = 0)
:m_hour(hour), m_minute(minute), m_second(second)
{}
private:
int m_hour;
int m_minute;
int m_second;
};
class Date
{
public:
Date(int year, int month, int day) :m_year(year), m_month(month), m_day(day)
{}
private:
int m_year;
int m_month;
int m_day;
Time t;//前提是Time类中有默认构造函数(全缺省构造也为默认构造);
public:
void DatesetTime(int hour, int minute, int second)
{
t.m_hour = hour;
t.m_minute = minute;
t.m_second = second;
}
};
特征:
1.友元关系是单向的;
2.友元关系不能传递;
二、static
声明为static的类成员为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态的成员变量一定要在类外进行初始化。
剑指offer64题:求1+2+…+n,要求不能使用乘除、for、while、、if、switch等关键字及条件判断语句。
class Solution {
public:
class Sum
{
public:
Sum()
{
_sum += _i;
_i++;
}
};
int Sum_Solution(int n) {
_i = 1;
_sum = 0;
Sum array[n];
return _sum;
}
static size_t _sum;
static size_t _i;
};
size_t Solution::_sum = 0;
size_t Solution::_i = 1;
特征:
1.静态成员为类对象所共享,不属于某个具体的实例;
2.静态成员变量必须在类外定义,定义时不添加static关键字;
3.类静态成员即可用类名::静态成员或者对象.静态成员访问;
4.静态成员函数没有隐藏的this指针(友元也没有且级别低于静态成员函数),不能访问任何非静态成员;
5.静态成员和类的普通成员一样,也有public、protected、private三种访问级别,也可以具有返回值;
6.普通成员函数可以调用静态成员变量及静态成员函数,而反之不能。
总结
朋友的朋友不一定是朋友;我拿你当朋友,你却不让我抄你作业。