现在的位置: 首页 > 综合 > 正文

不用友元的疑问——为什么要用friend关键字?

2014年03月14日 ⁄ 综合 ⁄ 共 1995字 ⁄ 字号 评论关闭
//---------------------------------------------------------------------------

#include <vcl.h>             //CB6.0
#include <iostream>
using namespace std;
//---------------------------------------------------------------------------
class Complex
{
public:
    Complex(double r=0.0, double i=0.0) { real = r; imag = i; }
    void display() const  { cout<<real<<'+'<<imag<<'i'; }

    Complex add(const Complex& x)const ;

    void    complex_add(const Complex& x, const Complex& y) ;   //非友元,为什么可行?

    //friend
    Complex complex_add2(const Complex& x, const Complex& y);

private:
    double real;
    double imag;
};

//---------------------------------------------------------------------------
//如何实现两个复数相加?
Complex Complex::add(const Complex& x) const
{
    Complex temp;
    temp.real = this->real + x.real;
    temp.imag = this->imag + x.imag;
    return temp;
}
//---------------------------------------------------------------------------
void Complex::complex_add(const Complex& x, const Complex& y)   //非友元函数
{
    this->real = x.real + y.real;
    this->imag = x.imag + y.imag;
}
//---------------------------------------------------------------------------
Complex Complex::complex_add2(const Complex& x, const Complex& y)   //一定要是友元函数?为什么?
{
    Complex temp;
    temp.real = x.real + y.real;      //非友元情况下temp不能访问real,为什么?
    temp.imag = x.imag + y.imag;
    return temp;
}
//---------------------------------------------------------------------------

//测试代码:
int main(int argc, char* argv[])
{
    Complex a(1.0, 2.0), b(3.0, 5.0), c;
    //c = a.add(b);              // OK

    //c.complex_add(a,b);        // OK

    c = complex_add2(a,b);       // ?why not?
     
    c.display();

    return 0;
}

如类的声明中描述的那样,假设 complex_add2 函数不被声明为类Complex的友元,那么在测试代码中,

c = complex_add2(a,b); // ?why not?

这一行就不能通过编译,这是为什么呢?它不是已经被声明为成员函数了吗?

原来,上面这种函数调用方法,正是友元的常见调用形式!

 

如果你需要将 complex_add2 作为 Complex的成员函数来调用,那么正确的调用方式应该是:

"某Complex对象.complex_add2(a,b);"

只要这个对象是有效的,那么其返回值就可以正确赋值给c。

比如:c=a.complex_add2(a,b);

又比如:c=c.complex_add2(a,b);

而不必关心是谁(Which available object)调用了该成员函数。

 

成员函数的调用方式与友元之不同正体现于此,这也在测试代码 add 以及 complex_add  函数的调用方法中得以展现。

 

*************************

 

此外,如果被声明为成员函数,那么在函数定义时,函数名前加作用域“Complex::”是不可避免的。

 

如果直接使用 c=complex_add2(a,b); 那么编译器会提示调用了一个未被定义的函数complex_add2,这也间接提示编辑者,该调用方法是有问题的。

 

原贴见:http://bbs.csdn.net/topics/390326324

抱歉!评论已关闭.