C++基础--友元
来源:互联网 发布:路基压实度灌砂法软件 编辑:程序博客网 时间:2024/05/16 06:59
假定我们已经定义了两个集合类变量,一个为整型数集合,另一个为实型数集合:
程序段10-7
class IntSet {
public:
//...
private:
int elems[maxCard];
int card;
};
class RealSet {
public:
//...
private:
float elems[maxCard];
int card;
};
void IntSet::SetToReal (RealSet &set)
{
set.EmptySet();
for (register i = 0; i < card; ++i)
set.AddElem((float) elems[i]);
}
class RealSet {
//...
friend void IntSet::SetToReal (RealSet&);
};
void IntSet::SetToReal (RealSet &set)
{
set.card = card;
for (register i = 0; i < card; ++i)
set.elems[i] = (float) elems[i];
}
其实,我们也可以把一个类定义为另一个类的友元,例如:
class A;
class B {
//...
friend class A;
};
类A是类B的友元,类A中的所有成员函数都能访问类B的私有成员。
全局函数也可以作为类的友元。例如,假定我们将SetToReal定义为全局函数,并定义为IntSet和RealSet两个类的友元:
程序段10-10
class IntSet {
//...
friend void SetToReal (IntSet&, RealSet&);
};
class RealSet {
//...
friend void SetToReal (IntSet&, RealSet&);
};
void SetToReal (IntSet &iSet, RealSet &rSet)
{
rSet.card = iSet.card;
for (int i = 0; i < iSet.card; ++i)
rSet.elems[i] = (float) iSet.elems[i];
}
虽然友元为我们进行程序设计提供了一定的方便性,但是面向对象的程序设计要求类的接口与类的实现分开,对对象的访问通过其接口函数进行。如果直接访问对象的私有成员,就破坏了面向对象程序的信息隐藏和封装特性,虽然提供了一些方便,但有可能是得不偿失的,所以,我们要慎用友元。
C++的存取控制
C++有三个关键字,用于设置类成员的访问权限,它们是:public、private和protected。
◇ public意味着在其后声明的所有成员在类外可以访问;
◇ private关键字则意味着,除了该类的成员函数之外,类外不能访问这些成员。如果试图访问私有成员,就会产生编译错误。类中缺省访问权限说明的的成员声明是private的;
◇ protected和private区别在于:protected成员可以被派生类访问,而private成员则不能被派生类访问。
友元的使用
类的私有成员只能在类内访问,那么有没有可能让类外的成员访问?其实,在C++中,友元可以访问类的私有成员。友元不是类的成员,但必须在类的内部声明。因为"谁是我的朋友"必须由"我自己决定"。绝对不能允许下面的现象发生:李四说,"嘿,我是张三的朋友",然后李四就开始使用张三的一切,包括它的私有财产。李四究竟是不是张三的朋友,必须由张三自己说了算。
通过friend关键字,可以把一个全局函数声明为友元,也可以把另一个类中的成员函数,甚至整个类都声明为友元,请看下面的例子:
例10-25
class X; //Declaration
class Y
{
void f(X*);
};
class X
{
private:
int i;
public:
void initialize();
friend void g(X*, int); //Global friend
friend void Y::f(X*); //class member friend
friend class Z; //Entire class is a friend
friend void h();
};
void X::initialize()
{
i = 0;
}
void g(X* x, int i)
{
x->i = i;
}
void Y::f(X* x)
{
x->i = 100;
}
class Z
{
private :
int j;
public:
void initialize();
void g(X* x);
};
void Z::initialize()
{
j = 99;
}
void Z::g(X* x)
{
x->i += j;
}
void h()
{
X x;
x.i = 200; //直接数据操作
}
void main()
{
X x;
Z z;
z.g(&x);
}
解决的办法是:首先声明类X,但是这个类X的声明并不完整,能行吗?在本例中是可以的,这是由于Y::f(X*)的参数是指向X对象的指针,所以编译器允许在声明Y::f(X*)之前做一个不完全的类型指定。仅仅是告诉编译器,有一个叫X的类。这样,在类X中,Y::f(X*)就可以成功地声明为一个友元函数。
再来看看其它两个友元函数,第一个声明将一个全局函数g()作为一个友元,但g()在这之前并没有定义,这表明friend可以同时声明全局函数和友元。同样,friend可以同时声明类Z及类Z作为类Y的友元。
嵌套友元
对于嵌套类,也不能访问私有成员。嵌套类要访问私有成员也必须定义为友元。请看下面的例子:
例10-26
#define SZ 20
class holder
{
private:
int a[SZ];
public:
void initialize();
class pointer
{
private:
holder *h;
int* p;
public:
void initialize(holder* H);
//move around in the array.
void next();
void previous();
void top();
void end();
//access values.
int read();
void set(int i);
};
friend holder::pointer;
};
friend holder : :pointer ;
关于友元的使用
如果一个函数被某一个类声明为friend,就意味着它不是这个类的成员函数,但却可以访问该类的私有成员,而且它必须被列在类的定义中。虽然友元这种机制为我们进行程序设计提供了一定的方便性,但是,面向对象的程序设计要求类的接口与类的实现分开,对对象的访问通过其接口函数进行。如果直接访问对象的私有成员,就破坏了面向对象程序的信息隐藏和封装特性,虽然提供了一些方便,但有可能是得不偿失的,所以,我们要慎用友元。
- c/c++基础(十九) 友元
- C++基础--友元
- 【Linux基础】友元
- C++基础:友元
- C++基础---友元
- C#_基础概念_元组
- C++(一)友元
- [C++]友元学习
- [c++]友元函数
- [c++] 友元详解
- 【C++】友元函数
- c++:友元函数
- C++:友元函数
- C++:友元
- C/C++ 友元
- 【C++】友元函数
- C++:友元
- C++----友元
- PHP/MySQL Dev. Primer (1) Establish Env.
- Mysql,Oracle,Sqlserver数据库连接
- WCF大文件断点下载示例
- 三个超强JSP防SQL注入攻击方法
- Android常用RGB值以及中英文名称
- C++基础--友元
- checked全选,全不选
- Struts2 结果类型
- 稳定排序和不稳定排序
- 认真地找工作
- RJ45 网线接口介绍
- Android的语言设置(一)
- Android的语言设置(二)
- java获取当前工程目录