我们为什么要使用友元函数来定义比较运算符?

时间:2012-02-28 05:42:22

标签: c++ friend-function

来自http://www.learncpp.com/cpp-tutorial/142-function-template-instances/

class Cents
{
private:
    int m_nCents;
public:
    Cents(int nCents)
        : m_nCents(nCents)
    {
    }

    friend bool operator>(Cents &c1, Cents&c2)  // <--- why friend?
    {
        return (c1.m_nCents > c2.m_nCents) ? true: false;
    }
};

我们也可以像这样实现它:

class Cents
{
private:
    int m_nCents;
public:
    Cents(int nCents)
        : m_nCents(nCents)
    {
    }

    bool operator> (Cents& c2)  // <---
    {
        return (this->m_nCents > c2.m_nCents) ? true: false;
    }
};

使用第二种实现是否有任何缺点?

4 个答案:

答案 0 :(得分:11)

假设您使用const引用作为参数,第一个实现可以在这样的条件下使用:bool b = 42 > c;这将在第二个实现中提供编译器错误。这将使用整数Cent自动创建42对象(因为构造函数未定义为explicit),然后使用friend函数进行比较。请参阅此FAQ

中的第7点

答案 1 :(得分:0)

第一个定义为类成员重载运算符,第二个是非成员重载运算符。当非成员函数访问私有成员时 应该添加private: int m_nCents;friend。即使我更改为public:int m_nCents;,它也不起作用。friend似乎是一个规则,而不是因为成员访问限制。但是您可以将Nonmember运算符移出类主体并访问公共成员变量。有什么好主意吗?我感到困惑。我认为 ALL 非成员运算符(与操作数具有相同的参数号,不能作为成员函数调用)必须在类体中声明为friend

>是一个二元运算符,每个操作数都有两个参数。您发现类成员重载运算符>只有一个显式参数和一个隐式this参数。非成员运营商必须有两个。

class Cents{
  private:
     int m_nCents;
  public:
  Cents(int nCents)
     : m_nCents(nCents)
   {
   }

   friend bool operator>(Cents &c1, Cents&c2); //Nomember 

   bool operator<(Cents &c1); //class member
};

bool operator>(Cents &c1, Cents&c2)  // <--- why friend?
{
   //cout << "in >"  << endl;
   return (c1.m_nCents > c2.m_nCents) ? true: false;
}

bool Cents::operator<(Cents &c1)
{
    //cout << "in <"  << endl;
    return (this->m_nCents < c1.m_nCents) ? true: false;
}

int main(){
 //nomember
 //if(poor.operator>(rich))  //compiler error 
 if(poor > rich){
     cout << "oh yeal!" << endl;
 }
 else
 {
     cout << "oh no!" << endl;
 }

 //member
 //if(poor.operator<(rich)) //can call this way
 if(poor.operator<(rich)){
     cout << "oh yeal!" << endl;
 }
 else
 {
     cout << "oh no!" << endl;
 }

}

我将实现移出了类体。现在,您可以看到类成员运算符具有Cents::限定符,就像成员函数一样。

答案 2 :(得分:-1)

我认为大多数实际例子一般没有太大区别。

我更喜欢第二个选项,它直接与class相关联。而且,以下语法更合适:

bool operator> (const Cents& c2) const
{         //    ^^^^^            ^^^^^
  return (this->m_nCents > c2.m_nCents); // simple
}

答案 3 :(得分:-2)

没有理由与朋友标记公共方法。朋友函数对访问私有或受保护成员的无关类很有用。

那就是说,你可以放弃第一个实现的朋友,它会正常工作。