C++友元

转载 2008年09月30日 19:22:00

1,friend申明一个友元

friend一般为一句申明式,它位于一个类的内部,它申明一个类或者一个函数为该类的友元。friend并不是定义一个成员函数,所以friend放在public,protected或者private前都可以,完全是一样的。做为一个友元,即表示在该类或者该函数内部可以访问这个类的私有成员,你和朋友之间是不是应该没有什么隐藏的呢。例子:

class A
{
public:
 A(int _a) : a(_a) {}
 friend void test(A&);
 friend class B;
private:
   int a;
};

void test(A& x)
{
 x.a=100;//拥有私有成员a的访问权限
}

class B
{
public:
  void foo();
};

如果friend申明式为一般的非模板类或者函数,则该处可以为首次申明。对于一个类,只能是申明式,对于函数,可以是它的定义式。

class A
{
public:
 A(int _a) : a(_a) {}
 friend void test(A& x)
 {
    x.a = 100;//定义::test()友元函数
 }
 friend class B;
private:
   int a;
};

注意尽管将函数的定义式放在类内部,但它并不是一个成员函数,对于省略受限的定义形式它将成为一个全局函数::test(),当然你也可以申明另外一个类的成员函数为友元,如:

class A
{
public:
 A(int _a) : a(_a) {}
 friend void B::foo();
private:
   int a;
};

总的来说,如果你想在哪里访问类A的私有成员,就在类A内写上一句该处的申明式,并在前面加上friend关键字。

这是一般情况,很简单,但是它会破坏封装的初衷,所以尽量少用;Effective C++中有一个应用的例子,对一个类定义的二元操作符,如果你希望它能对操作数都进行隐式转化,那么就定义一个全局函数,并申明成该类的友元。

2,模板函数作友元

先给一个模板函数,它是一个模板,并不是一个函数:

template<typename T>
void foo1(T);

在定义foo1为某类的友元时,或者要实例化模板参数T,或者给出可演绎的申明式,而且就算是可以演绎的,一对尖括号也不能省。如:

class A
{
public:
  friend void foo1<char>(char);
  friend void foo1<>(double);
};

或者给出限制符:::

class A
{
public:
  friend void ::foo1(char);
};

当然,如果有一般函数具有这种形式,那会优先于模板函数匹配。最后这里的申明式都不能是定义式,必须前至申明(定义)。

3,模板类里的友元

模板类里也能申明2中的友元,但是模板类有模板参数,如果利用了这个模板参数的友元申明,就属这种情形。

template<typename T>
class A
{
public:
  friend void foo1<T>(T);
};

但是,在这里,必须要求foo1在这里是可见的,即不能是首次申明式。如果不使用模板参数,那会是一种有趣的情形。

template<typename T>
class A
{
public:
  friend void foo(){}
};

注意这里是一个定义式,它定义了一个::foo()函数为该模板类的友元,在该模板类具现的时候,::foo()也被具现出来,即:

A<int> a1;// ::foo()首次定义
A<char> a2;// ::foo()第二次定义,违背C++一次定义原则

4,友元模板

如果想定义一系列函数为该类的友元,可以使用友元模板。它和模板的申明式类似,只是在template<>后加了friend关键字。

class A
{
public:
 template<typename T>
 friend void foo();
};

5,能否做为定义式

能做为定义式的情况是:非受限,没有前至::,没有模板参数列表,没一对尖括号。如果是模板申明式,不能是首次申明,在该处必须是可见的。

6,一个完整的例子

template<typename T>
class Rat
{
public:
    Rat(T _a, T _b) : a(_a), b(_b) {}
    friend Rat<T> operator*<T>(Rat<T>&,Rat<T>&);
private:
    T a,b;
};

template<typename T>
Rat<T> operator*(Rat<T> & x, Rat<T> & y)
{
    return Rat<T>(x.a*y.a,x.b*y.b);
}

Rat<T>为T类型的有理数类,定义它的相乘运算,定义一个全局函数,并申明为友元,该函数也应该是模板,希望有如上的程序通过编译。在friend式之前没有operator*()的申明,所以这里不能是首次申明,在前面必须加上申明式:

template<typename T>
Rat<T> operator*(Rat<T> & x, Rat<T> & y);

在这之前又没有Rat<T>的申明,再加上:

template<typename T>
class Rat;

通过编译,或者改成友元模板:

template<typename T>
class Rat
{
public:
    Rat(T _a, T _b) : a(_a), b(_b) {}
    template<typename U>
    friend Rat<U> operator*(Rat<U>&,Rat<U>&);
private:
    T a,b;
};

template<typename T>
Rat<T> operator*(Rat<T> & x, Rat<T> & y)
{
    return Rat<T>(x.a*y.a,x.b*y.b);
}

有细微的不同,Rat<T>申明了一系列友元operator*<U>,当然没必要,只要operator*<T>就够了,但是形式上简单一些。还有一种更简单的形式,就是将定义式放在里面,正是Effective C++里使用的方法:

template<typename T>
class Rat
{
public:
    Rat(T _a, T _b) : a(_a), b(_b) {}
    friend Rat<T> operator*(Rat<T>&x,Rat<T>&y) //定义并申明了::operator*()
    {
        return Rat<T>(x.a*y.a,x.b*y.b);
    }
private:
    T a,b;
};

c++友元实现操作符重载

运算符重载的本质是一个函数#include using namespace std;class A { private: int m_a; int m_b; friend A ...
  • sjtu_chenchen
  • sjtu_chenchen
  • 2015年08月22日 16:14
  • 1887

C++ 运算符流操作符重载和友元--笔记

/************************************************************************************************ *...
  • JarvisChu
  • JarvisChu
  • 2011年07月23日 20:57
  • 5615

C++类模板友元声明的几种情况

根据《C++ Primer》第三版16.4节的叙述,C++类模板友元分为以下几种情况 1.非模板友元类或友元函数。 书上给了一个例子: class Foo{     void bar(); }...
  • hqz1989
  • hqz1989
  • 2014年03月24日 11:32
  • 1858

C++中模板类的友元重载

一个由《程序员面试宝典》引出的问题。 描述模板类的友元重载,用C++代码实现? 这实际上考察的是下面几个问题: 1.模板类的编写 2.模板类中友元函数的编写 3.什么时候会用到友元重载?答案...
  • u012501459
  • u012501459
  • 2015年03月10日 16:41
  • 1740

为什么要引入友元机制

【一】为什么引入友元机制?     总的来说就是为了让非成员函数即普通函数或其他类可以访问类的私有成员,这确实破坏了类的封装性和数据的隐蔽性,但为什么要这么做呢? (c++ primer:尽管友元...
  • pipinuan
  • pipinuan
  • 2016年10月18日 13:47
  • 793

C++中的友元——编程界的老王

c++中友元类可以访问类的所有域,简直是编程世界的老王。
  • qyvlik
  • qyvlik
  • 2015年08月09日 13:13
  • 945

C++运算符重载(注意点),友元(使用和优缺点)

运算符重载实例代码class A{ public: int a,b; A(int _a=0,int _b=0):a(_a),b(_b){} A operator+(A & tm...
  • qq_26437925
  • qq_26437925
  • 2016年12月26日 19:12
  • 441

C++之派生类的友元

先举个例子:#include using namespace std;class Student{ private: int _a; int _b; public: Stude...
  • maoliran
  • maoliran
  • 2016年06月10日 15:18
  • 480

C++之嵌套类与外围类及友元

class Outer { public: Outer(){m_outerInt=0;} private: int m_outerInt; public: //内部类定义开始 ...
  • gettogetto
  • gettogetto
  • 2016年05月11日 17:14
  • 593

C++(11):友元、嵌套类

关于“友元”和“嵌套类”一些用法上的说明。
  • qcyfred
  • qcyfred
  • 2016年12月22日 20:50
  • 358
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++友元
举报原因:
原因补充:

(最多只允许输入30个字)