C++][基础知识4] 友元函数

四 友元函数
为了强调类的数据封装性,常将一些关键成员设为私有访问特性或保护访问特性。这样,在类的外面只能通过类的成员函数来访问这些成员,有时会觉得类的这种特性很不方便。但是,如果将这些成员的访问特性设为公有的,则又失去了类的封装性。为了解决这个矛盾,VC++中引入了友元函数的概念。对于某一个类来说,该类的友元函数可以是一个不属于任何类的普通函数,也可以是另一个成员函数。
 1 友元函数的说明及使用
如果在一个类中使用关键字friend对一个不属于该类的外部函数进行说明,则外部函数就成为该类的友元函数,它可以访问该类的任何成员。例如:

#include<iostream.h>
class A{
int a,b;
friend void print(A);
public:
A(int x,int y)
{a=x;b=y;}
friend void show(A *p)
{
cout<<p->a<<'\n';
cout<<p->b<<'\n';
}
};
void print(A t)
{
cout<<t.a<<'\n';
cout<<t.b<<'\n';
}
void main()
{
A a1(10,20);
print(a1); //A行
show(&a1); //B行
}

在类中可以只对友元函数进行原型说明(如上面的友元函数print()),也可以在类中对友元函数进行定义(如上面的友元函数show())。
友元函数不是类的成员函数,所以在友元函数中对类的对象的成员进行访问时必须指明该成员所属的对象。
同样,由于友元函数不是类的成员,所以,友元函数是不受类中访问特性的限制的,如上例中的友元函数print(),虽然它是与私有成员一起说明的,但它的使用与友元函数show()一样不受类的访问权限的限制,并且在调用这些友元函数时也是直接调用,如程序中的A行和B行不能写成A.print(a1)和A.show(&a1)。
由于友元函数破坏了类的封装性,所以,它的使用有可能对程序带来一些不利的影响。通常,在友元函数中不修改类的成员数据而只用于读取类成员的数据。
 2 友元成员函数及友元类
一个类放入友元函数可以是另一个类的成员函数,并且,如果将一个类说明为某类的友元类,则友元类的所有成员函数均为该类的友元函数。

#include<iostream.h>
class C;
class A{
int a,b;
public:
A(int x,int y)
{a=x;b=y;}
void addA(C &t); //A行
};
class B{
public :
void sub(C &t); //B行
void show(C t);
};
class C{
int a,b;
public:
C(int x,int y)
{a=x;b=y;}
friend void A::addA(C &t); //说明A的成员函数为友元
friend class B; //说明类B为友元
};
void A::addA(C &t)
{
t.a+=a;
t.b+=b;
}
void B::sub(C &t)
{
t.a--;
t.b--;
}
void B::show(C t)
{
cout<<t.a<<'\t'<<t.b<<'\n';
}
void main()
{
A a1(10,20);
B b1;
C c1(30,40);
b1.show(c1);
a1.addA(c1);
b1.show(c1);
b1.sub(c1);
b1.show(c1);
}

其中,由于类A和类B的成员函数中均用到了类C的对象,所以类C在类A和B之后定义,则在使用它之前给出类C的说明,并且,程序中用到类C的对象的几个成员函数的函数体也只能在类C之后定义(如程序中的A,B,C行的函数)。当然,如果类C在类A和B之前定义,则无上述必要。
上述程序在类C中将类B说明为友元类,则表示类B的所有成员函数均为类C的友元函数。但这种友元关系是不可逆的,即类B为类C的友元并不代表类C也为类B的友元。
上述程序运行结果:
30 40
40 60
39 59
 3 抽象类与友元函数
由于某些特殊需要,如果设计类的构造函数为私有或保护访问特性,则在正常情况下该类不能用来生成对象,但如果将某函数定义为该类的友元,则可以在该函数中生成该类的对像。如:

#include<iostream.h>
class A{
int a,b;
protected:
A(int x,int y)
{a=x;b=y;}
friend A fun();
friend void main();
};
A fun()
{
A t(10,20);
return t;
}
A a1(fun());
void main()
{
cout<<a1.a<<'\t'<<a1.b<<'\n';
}

程序中类A的构造函数为保护访问特性,正常情况下不可以产生对象。但可以通过其友元函数来返回一个对象,这个返回的对象用来拷贝出一个全局作用域的对象a1(程序中的A行)。同时,由于主函数也为类A的友元,所以在主函数中可以输出对象a1的成员函数。程序运行输出如下:
10 20
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值