friend在c++中使用

应用:

PG1.m_VecPt == PG2.m_VecPt 1

PG1nestPolygon类的对象,m_VecPtnestPolygon类的成员变量,定义如下:

vector<nestPoint2D> m_VecPt; 因为nestPoint2D不是内建类型,所以不能直接使用==等号,所以需要重载==

class  AFX_EXT_CLASS nestPoint2D

{

       Friend bool operator==(const nestPoint2D& npt1, const nestPoint2D& npt2);

}

 

展开:

1、整个类可以是另一个类的友元,该友元也可以称做为友类。

class Internet;
  class Country
  {

friend class Internet;//友类的声明,形象的说:InternetCountry的朋友

};

这样Internet类中的成员函数可以通过函数参数(也就是Country对象或者Country对象引用)访问Country类的私有成员。

(理解:Country声明 Internet是是它的友元(朋友),那么 Country就信任Internet,所以在Internet中的成员函数,通过Country对象或者Country对象引用就能够访问Internet的私有数据)

迭代器中也有类似的用法:(实质上这个是嵌套友元类的用法,同时这也是一种设计模式)

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类的私有成员。

 (理解:在Internet中 申明Country的成员函数Editurl是Internet的友元函数,那么Internet 信任该函数,所以函数Country::Editurl可以通过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;
 };

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值