私有成员只能在类的成员函数内部访问,若是想在别处访问对象的私有成员,只能经过类提供的接口(成员函数)间接地进行。这当然可以带来数据隐藏的好处,利于未来程序的扩充,但也会增长程序书写的麻烦。
C++ 是从结构化的C语言发展而来的,须要照顾结构化设计程序员的习惯,因此在对私有成员可访问范围的问题上不可限制太死。
C++ 设计者认为, 若是有的程序员真的很是怕麻烦,就是想在类的成员函数外部直接访问对象的私有成员,那仍是作一点妥协以知足他们的愿望为好,这也算是眼前利益和长远利益的折中。所以,C++ 就有了友元(friend)的概念。打个比方,这至关因而说:朋友是值得信任的,因此能够对他们公开一些本身的隐私。
友元分为两种:友元函数和友元类。html
在定义一个类的时候,能够把一些函数(包括全局函数和其余类的成员函数)声明为“友元”,这样那些函数就成为该类的友元函数,在友元函数内部就能够访问该类对象的私有成员了。
将全局函数声明为友元的写法以下:ios
friend 返回值类型 函数名(参数表);程序员
将其余类的成员函数声明为友元的写法以下:函数
friend 返回值类型 其余类的类名::成员函数名(参数表);spa
可是,不能把其余类的私有成员函数声明为友元。
关于友元,看下面的程序示例。.net
这个程序只是为了展现友元的用法,因此 main 函数什么也不作。
第 3 行声明了 CCar 类,CCar 类的定义在后面。之因此要提早声明,是由于 CDriver 类的定义中用到了 CCar 类型(第7行),而此时 CCar 类尚未定义,编译会报错。
不要第 3 行,而把 CCar 类的定义写在 CDriver 类的前面,是解决不了这个问题的,由于 CCar 类中也用到了 CDriver 类型(第14行),把 CCar 类的定义写在前面会致使第 14 行的 CDriver 因没有定义而报错。C++ 为此提供的解决办法是:能够简单地将一个类的名字提早声明,写法以下:设计
class 类名;指针
尽管能够提早声明,可是在一个类的定义出现以前,仍然不能有任何会致使该类对象被生成的语句。但使用该类的指针或引用是没有问题的。
第 13 行将全局函数 MostExpensiveCar 声明为 CCar 类的友元,所以在第 24 行能够访问 cars[i] 的私有成员 price。同理,第 14 行将 CDriver 类的 ModifyCar 成员函数声明为友元,所以在第 18 行能够访问 pCar 指针所指向的对象的私有成员变量 price。htm
一个类 A 能够将另外一个类 B 声明为本身的友元,类 B 的全部成员函数就均可以访问类 A 对象的私有成员。在类定义中声明友元类的写法以下:对象
friend class 类名;
来看以下例程:
第 5 行将 CDriver 声明为 CCar 的友元类。这条语句原本就是在声明 CDriver 是一个类,因此 CCar 类定义前面就不用声明 CDriver 类了。第 5 行使得 CDriver 类的全部成员函数都能访问 CCar 对象的私有成员。若是没有第 5 行,第 13 行对 myCar 私有成员 price 的访问就会致使编译错误。 通常来讲,类 A 将类 B 声明为友元类,则类 B 最好从逻辑上和类 A 有比较接近的关系。例如上面的例子,CDriver 表明司机,CCar 表明车,司机拥有车,因此 CDriver 类和 CCar 类从逻辑上来说关系比较密切,把 CDriver 类声明为 CCar 类的友元比较合理。 友元关系在类之间不能传递,即类 A 是类 B 的友元,类 B 是类 C 的友元,并不能导出类 A 是类 C 的友元。“咱俩是朋友,因此你的朋友就是个人朋友”这句话在 C++ 的友元关系上 不成立。