写在前面的话:C++ 语言中的友元为封装隐藏这堵不透明的墙开了一个小孔,外界可以通过这个小孔窥视内部的实现机制。但友元破坏了类的封装性和数据的隐蔽性,导致程序可维护性变差。
友元有3种:
- 友元函数
- 友元类
- 友元成员函数
注:1. 友元不具有传递性。A是B的友元,B是C的友元,但A不是C的友元。
2. 友元关系是单向的,不具有交换性。A是B的友元(即在B里声明A为友元类),B不是A的友元。
一.友元函数
友元函数常常用来重载二元运算符。
创建友元函数:
1.将其原型放在类声明中,并在原型中加上关键字friend。
friend Time operator*(double m, const Time & t);
- 虽然operator*()是在类声明中声明的,但它不是成员函数,因此不能使用成员运算符来调用。
- 虽然不是成员函数,但它与成员函数的访问权限相同。
- 友元函数不是类的成员,所以没有this指针。
- 如果再说嘛友元的时候给出了该函数的函数体代码,则它是内联的。
2.编写函数定义
Time operator*(double m, const Time & t);
{
Time result;
.....
}
- 不要在定义中使用friend
- 不要使用Time::限定符
例1:
#include <iostream>
#include <string>
class Student
{
private:
char name[10],num[10];
friend void show(Student&st) //友元函数的声明和定义
{
cout<<"Name:"<<st.name<<endl<<"Number:"<<st.num<<endl;
}
public:
Student(char *s1,char *s2)
{strcpy(name,s1);strcpy(num,s1);}
};
class Score
{
unsigned int mat,phy,eng;
friend void show_all(Student&,Score*);
public:
Score(unsigned int i1,unsigned int i2,unsigned int i3)
:mat(i1),phy(i2),eng(i3);
{}
};
void show_all(Student&st,Score *sc)
{
show(st);
cout<<"Mathematic"<<sc->st;
}
void main()
{
Student wang("wang","9901");
Score ss(72,82,92);
show_all;
}
两个友元函数都是全局作用域独立定义的函数,全局可用函数。
例2:
#include strmax 32
#include <string.h>
#include<iostream.h>
class myclass
{
int x,y;
char *string;
public:
myclass(int vx,int vy,char *str);
friend int num(myclass c1);
friend int strlength(myclass s1);
friend void print(myclass c1);
};
myclass::myclass(int vx,int vy,car *str)
{
x=xy;
y=vy;
string = new char[strmax];
strcpy(string,str);
}
int num(myclass c1)
{return c1.x+c1.y;}
int strlength(myclass c1)
{return strlen(c1.string);}
void print(myclass c1)
{
cout<<"x="<<c1.x<<"y="<<c1.y<<endl;
cout<<"string:"<<c1.string<<endl;
}
void main()
{
myclass c1(10,10,"my myclass object!");
cout<<"the sum is"<<sum(c1)<<endl;
cout<<“the string is:”<<strlength(c1)<<endl;
print(c1);
}
二.友元成员
另一个类的成员函数可以作为某个类的友元,只是在声明友元函数时要加上成员函数所在的类名,成为友元成员。
声明如下:
friend 函数返回值类型 类名::成员函数名(形参列表);
与上一种友元比较,此种友元的存取范围要小很多。因为这里的友元函数只是一个类中的一个成员,friend授权该函数可以访问宣布其为友元的类中的所有成员。
#include <iostream.h>
#include <string.h>
class Student; //声明引用的类名
class Score
{
unsigned int mat,phy,eng;
public:
Score(unsigned int i1,unsigned int i2,unsigned int i3):mat(i1),phy(i2),eng(i3){}
void show(Student&);
};
class Student
{
friend void Score::show(Student&); //声明友元成员
char name[10],num[10];
public:
Student(char *s1,char *s2){strcpy(name,s1);strcpy(num,s2);}
};
void Score::show(Student& st)
{
cout<<"Name:"<<st.name<<"\n";
show();
}
void main()
{
Student wang("Wang","9901");
Score ss(72,82,92);
ss.show(wang);
}
三. 友元类
某一个类是另一个类的友元,这样作为友元的类中的所有成员函数都可以访问声明其为友元类的类中的全部成员。
说明方式:
friend class <类名>;
例1:
#include<iosteam>
#include<string>
class Student
{
friend class Score; //声明Score类为Student类的友元类
char name[10],num[10];
public:
Student(char *s1,char *s2)
{strcpy(name.s1);strcpy(num.s2);}
};
class Score
{
unsigned int mat,phy,eng;
public:
Score(unsigned int i1,unsigned int i2,unsigned int i3)
:mat(i1),phy(i2),eng(i3)
{}
void show()
{
cout<<""<<mat<<phy<<eng<<endl;
}
void show(Student&);
};
void Score::show(Student& st)
{
cout<<"Name:"<<st.name<<"\n";
show();
}
void main()
{
Student wang("Wang","9901");
Score ss(72,82,92);
ss.show(wang);
}
注:由于声明Score类为Student类的友元类,此时Score类中的所有成员函数均可以直接访问Student类对象的成员。
这样Score的成员函数Show中的st.name的引用方式才是被允许的。