c++友元和内部类
1.友元声明
友元是c++突破封装的一种方式,在某些情况下很方便。但友元会增加耦合度,破坏了封装,不宜多用。
1.1 友元函数
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明需要加关键字**friend
**。
在使用友元函数时需注意:
1.友元函数可以访问类的私有和保护成员,但不是类的成员函数。
2.友元函数不能用const修饰。
3.友元函数可以在类的任何地方声明,不受类访问限定符限制。
3.友元函数可以是多个类的友元函数。
4.友元函数的调用与普通函数的调用相同。
在类中重载operator<<
时,成员函数重载的第一个参数必须是this指针,这导致了ostream& out
变成了右操作数,实际的调用方式与代码含义相反,十分别扭。
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
void operator<<(ostream& out)
{
out<<_year<<"年"<<_month<<"月"<<_day<<"日"<<endl;
}
private:
int _year;
int _month;
int _day;
};
这里的代码“cout流入d1”是正确的,但“d2流入cout”是错误的,显然与代码的含义不符。
于是,重载operator<<
就需要在类外进行,但如果类中的成员变量是私有成员变量,被重载成全局函数的operator<<
就无法访问。这时,就需要友元函数来突破封装了:
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
friend ostream& operator<<(ostream& out, const Date & d);//友元函数拥有成员函数相同的权限
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& out, const Date & d)//全局函数中可以让ostream& out作为第一个参数
{
out<<d._year<<"年"<<d._month<<"月"<<d._day<<"日"<<endl;
}
通过使用友元声明,可以保持成员变量的访问限定符不变,又让流提取的代码形式符合其含义
//流插入
istream operator>>(ostream& out, const Date & d)
{
cout>>"请输入年 月 日"<<endl;//可以在插入时在屏幕上输出一些提示信息
cin<<d._year<<d._month<<d._day<<endl;
}
1.2 友元类
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
友元关系是单向的,不具有交换性。
友元关系不能传递(如果C是B的友元,B是A的友元,则不能说明C时A的友元)。
class score
{
public:
score()
{
math = 100;
chinese = 100;
english = 100;
}
score(int _math, int _chinese, int _english)
{
math = _math;
chinese = _chinese;
english = _english;
}
void print()
{
cout << "math=" << math << endl;
cout << "chinese=" << chinese << endl;
cout << "english=" << english << endl;
}
private:
int math;
int chinese;
int english;
};
class student
{
friend class score;
public:
void show()
{
cout<<name<<age<<sex<<endl;
}
private:
char* name;
char* sex;
int age;
};
student可以访问score的私有成员,但score不能访问student的私有成员。
2. 内部类
如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对能去访问内部类的成员,外部类对内部类没有任何优越的访问权限。
注意:内部类就是外部类的友元类,内部类可以通过外部类的对象参数来访问外部类中的所有成质。但是外部类不是内部类的友元。
特征:
1.内部类可以定义在外部类的public、protected、private。
2.内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
3.sizeof(外部类)=外部类,和内部类没有任何关系。
class score
{
public:
class student
{
friend class score;
public:
void show()
{
cout << name << age << sex << endl;
}
void print(score& s)//内部类可以访问外部类的成员
{
cout << "math=" << s.math << endl;
cout << "chinese=" << s.chinese << endl;
cout << "english=" << s.english << endl;
}
private:
char* name;
char* sex;
int age;
};
score()
{
math = 100;
chinese = 100;
english = 100;
}
score(int _math, int _chinese, int _english)
{
math = _math;
chinese = _chinese;
english = _english;
}
void print()
{
cout << "math=" << math << endl;
cout << "chinese=" << chinese << endl;
cout << "english=" << english << endl;
}
private:
int math;
int chinese;
int english;
static int a;
};
int main()
{
score sc;
score::student st;
cout <<"sizeof(sc)="<<sizeof(sc) << endl;
return 0;
}
student类是score类的内部类,stduent类可以访问score的私有成员,但score不能访问student的私有成员。说明score是student的友元类,student不是score的友元类。
<<“sizeof(sc)=”<<sizeof(sc) << endl;
return 0;
}
> student类是score类的内部类,stduent类可以访问score的私有成员,但score不能访问student的私有成员。说明score是student的友元类,student不是score的友元类。
[外链图片转存中...(img-vdP1zkFb-1711452525692)]
> sizeof操作符只计算外部类成员变量所占的空间,和内部类没有关系。