| 
 
 
|  [c++读书笔记]friend的注意事项 |  
| 1、整个类可以是另一个类的友元,该友元也可以称做为友类。
class Internet;  class Country  {
friend class Internet;//友类的声明,形象的说:Internet是Country的朋友
};
这样Internet类中的成员函数可以通过函数参数(也就是Country对象或者Country对象引用)访问Country类的私有成员。
在迭代器中也有类似的用法:(实质上这个是嵌套友元类的用法,同时这也是一种设计模式)
Template<class T, int ssize = 100>
Class StackTemplate
{
     T stack[ssize];//private
     Int top;
     StackTemplate():top(0){} //constructor
 
     Class iterator;//forward declaration
     Friend class iterator; //让iterator类成为StackTemplate的友元类
     Class iterator //定义一个类
     {
         StackTemplate& s;
         Int index
         iterator (StackTemplate& st): s(st),index(0){}
         iterator (StackTemplate& st, bool):s(st),index(s.top){}
         T operator*() const { return s.stack[index];} 
//这里operator*()访问了StackTemplate类是私有成员
         //重载++,+ 等运算符
}
iterator begin() { return iterator(*this) }
iterator end() { return  iterator(*this, bool) }
}
使用:
StackTemplate<int> is;
StackTemplate<int>::iterator iterStart = is.begin();
StackTemplate<int>::iterator iterEnd = is.end();
 
2、一个类的成员函数可以是另一个类的友元
class Internet;  class Country  {  void Editurl(Internet &temp);//成员函数的声明  };
class Internet  {  friend void Country::Editurl(Internet &temp);//友元函数的声明  };
通过友元函数的参数Internet对象,访问Internet类的私有成员。
 
3、一个普通函数可以是(多个)类的友元函数。这类普通函数的参数都有类的对象,从而通过该对象,操作该类的私有成员,该函数被当作全局函数。
 
4、二元中缀运算符,如果第一个运算数不是类对象,通常把该函数声明为该类的友元函数。另外:在ostream的重载<<或者>>符号的时候,通常声明为友元函数。
 
5、友元关系既不继承,也不传递
我不见得信任我朋友的孩子。友元的特权不被继承。友元的派生类不一定是友元。如果 Fred 类声明Base类是友元,那么Base类的派生类不会自动地被赋予对于Fred的对象的访问特权。 
我不见得信任我朋友的朋友。友元的特权不被传递。友元的友元不一定是友元。如果Fred类声明Wilma类是友元,并且Wilma类声明Betty类是友元,那么Betty类不会自动地被赋予对于Fred的对象的访问特权。 
你不见得仅仅因为我声称你是我的朋友就信任我。友元的特权不是自反的。如果Fred类声明Wilma类是友元,则Wilma对象拥有访问Fred对象的特权,但Fred对象不会自动地拥有对Wilma对象的访问特权。 
6、友元函数主要缺点是需要额外的代码来支持动态绑定。
要得到虚友元(virtual friend)的效果,友元函数应该调用一个隐藏的(通常是 protected:)虚成员函数。
 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();  // "覆盖" f(Base& b)的行为   // ... };  void userCode(Base& b) {   f(b); } 
在userCode(Base&)中的f(b)语句将调用虚拟的  b.do_f()。这意味着如果b实际是一个派生类的对象,那么Derived::do_f()将获得控制权。注意派生类覆盖的是保护的虚(protected: virtual)成员函数 do_f(); 而不是它友元函数f(Base&)。 
一个使用虚友元函数用法更实际的例子:(为一个完整的继承层次的类提供打印)
 class Base { public:   friend std::ostream& operator<< (std::ostream& o, const Base& b);   // ... protected:   virtual void printOn(std::ostream& o) const; };  inline std::ostream& operator<< (std::ostream& o, const Base& b) {   b.printOn(o);   return o; }  class Derived : public Base { protected:   virtual void printOn(std::ostream& o) const; };
另见:http://tech.163.com/05/0405/14/1GJ664RL00091589.html
 
 |  
| 
 阅读全文(3946) | 回复(1) | 编辑 | 精华
 |  
 
| 回复:friend的注意事项 |  
| C++太难学了,学不会阿,还是java好学
 
 |  
| 
 个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除
 |  
 
| 回复:friend的注意事项 |  
| 
| Jeffern(游客)发表评论于2006/10/28 15:44:46 |  最近在业务上很用功!
 
 |  
| 个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除 |   »  1 » 
 
 | 
|   | « | October 2025 | » |  | 日 | 一 | 二 | 三 | 四 | 五 | 六 |  |  |  |  | 1 | 2 | 3 | 4 |  5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |  | |  | 
 |  
| 公告 |  
| 
| 有一种鸟儿是永远关不住的因为它的每片羽翼上都沾满了自由的光辉
 方向:计算机视觉 人工智能 演化算法   |  |  
 
 
 
 
 
| Blog信息 |  
| 
| blog名称:阳光海岸心日志总数:166
 评论数量:237
 留言数量:-4
 访问次数:1460237
 建立时间:2006年6月2日
 |  |   
 
 |