绝想首页

C++中友元的FAQ(Friend)

韩铮shady [沧桑] 2013-02-27 04:28:58 星期三 晴天 查看:135 回复:0 发消息给作者

什么是友元?
    友元使你的类准许另一个类或函数的访问。
    友元即可以是函数也可以是其他的类。一个类准许其友元有对其的访问特权。通常开发者对一个类的友元和成员函数拥有策略和技术上的控制(否则当你想升级你自己的类时,你可能需要获得该块的拥有者的许可)。


 


友元会破坏封装性吗?


    不会!事实上如果正确的使用,友元会加强封装性。
    当类的两部分有不同的实例数或生命周期,你经常需要把一个类切分开。在这种情况下,这两部分通常需要对彼此的直接访问(这两部分曾经在同一个类中,所以你没有增加代码量;你只是简单的把代码改组到两个类中)。
    如果你像刚描述的情形下使用友元,你保持private的成员为private。不懂得这个的人通常做出幼稚的举动,在上面的情况中避免使用友元,事实上他们经常会破坏了封装性。他们或使用public数据(奇形怪状的!),或者他们通过public get()和set()成员函数来使得数据在两部分间可访问。有一个public get()和set()成员函数对一个private数据来说仅当这个private数据在类的外部“有意义”(从一个使用者的视角)时才是可行的。在很多情况下,这些get()/set()成员函数差不多和public数据一样的差:他们(仅仅)隐藏了private数据的名称,并没有隐藏这个private数据的存在。
    类似的,如果你使用友元函数作为一个类的public访问函数的合法变量,也不会比一个成员函数更多的破坏封装性。换句话说,一个类的友元不会破坏封装的屏障。封装的屏障总是与类的成员函数一起出现的。
    (许多人认为成员函数是类之外的东西。换个思路,试着认为一个友元是类public接口的一部分吧。一个类声明中的友元函数不会比一个public函数更多的破坏封装性:他们对访问类的non-public部分都有确切相同的权限)。


 


友元的优缺点有哪些?
    他们在一定程度上为接口设计提供选择的自由。
    成员函数和友元函数有一样的特权(100%一样)。他们主要的区别在于友元函数如f(x)的形式被调用,而成员函数的调用时则使用x.f(x)的形式。因此在成员函数(x.f(x))和友元函数(f(x))中做出选择的能力使得开发者可以选择他认为更具可读性的语法,降低维护成本。
    友元函数的主要缺点是在你想动态邦定时需要一行额外的代码。要获得一个virtual友元,友元函数应该调用一个隐藏的(通常是protected)virtual成员函数。这个称为Virtual Friend Function Idiom。例如:


 class Base {
 public:
   friend void f(Base& b);
   
...

 protected:
   virtual void do_f();
   
...
 };
 
 inline void f(Base& b)
 {
   b.do_f();
 }
 
 class Derived : public Base {
 public:
   
...
 protected:
   virtual void do_f();  
// "Override" the behavior of f(Base& b)
   ...
 };
 
 void userCode(Base& b)
 {
   f(b);
 } 

    在userCode(Bace&)中f(b)的声明会调用b.do_f(),它是virtual的。这意味着如果b是一个Derived类的对象,Derived::do_f()将获得控制权。注意Derived覆写了protected virtual成员函数do_f();它没有自己的友元函数f(Base&)的变量。


 


“友元不是继承的,传递的,双向的”指什么?
    正是因为我允许你对我的友元访问,并不自动允许你的子类对我的访问,不自动允许你的友元对我的访问,不自动允许我对你的访问。
    我没必要相信我友元的子类。友元的特权不能够被继承。友元的派生类不是必要的友元。如果类Fred声明类Base是友元,从Base派生的类没有任何对Fred对象特定的自动的访问权限。
    我没必要相信我友元的友元。友元的特权不具有传递性。一个友元的友元没有必须是友元的必要。如果类Fred声明类Wlima为一个友元,雷Wilma声明类Betty为一个友元,类Betty没必要具有任何对Fred对象特定的访问权限。
    你没必要仅仅因为我声明你是我的友元就相信我。友元的特权不是双向的。如果类Fred声明类Wilma是其友元,Wilma的对象拥有特定的对Fred对象的访问,但是Fred的对象不会自动的拥有对Wilma对象特定的


访问权限。


 


我的类需要声明一个成员函数还是一个友元函数?
    能用成员函数时用成员函数,必须用友元函数时用友元函数。
    有时候友元在语句结构上更好(例如,在类Fred中,友元函数允许Fred的参数是第二个,而成员函数需要它作为第一个)。另一个友元函数的用处是二元中缀操作符。例如,aComplex + aComplex应该被定义为一个友元而不是一个成员,因为你也希望允许aFloat + aComplex进行(成员函数不允许left hand argument升级,因为那可能会改变作为这个对象调用容器的类)。
    在其他情况下,选择成员函数好些。


 


注:原文请查看http://www.juexiang.com/c++-faq-lite/friends.html#faq-14.2

顶一下(34 写日记 1163228 224336
上一篇:想你会不会爱上你下一篇:老师
分享排行

 

 

留住已经逝去的峥嵘岁月 记住曾经绽现的万种风情 在记忆即将淡漠的时候 来把这些重新回味

Copyright (C) 2008-2014 www.juexiang.com, All Rights Reserved.

京ICP备2023001011号-3   京公网安备11010802011908号

客服QQ 1017160561 违法和不良信息举报电话 13148464312 邮箱 1017160561@qq.com