C ++朋友类和朋友成员函数

时间:2017-06-28 15:14:59

标签: c++ class friend

我在C ++课程中学习朋友函数,朋友类和朋友成员函数; 现在,以下代码编译得很好:

#include <iostream>

class A 
{
public:
    friend class B;
    //friend void B::set(int i);
    //friend int B::get();
    friend int function(A a);
    A(int i);
    void set(int i);
    int get();
private:
    int i;
};

A::A(int i) : i(i)
{
}

void A::set(int i)
{
    this->i = i;
}

int A::get()
{
    return i;
}

class B
{
public:
    B(A a);
    void set(int i);
    int get();
private:
    A a;
};

B::B(A a) : a(a)
{
}

void B::set(int i)
{
    a.i = i;
}

int B::get()
{
    return a.i;
}

int function(A a);

int main(int argc, char *argv[])
{
    A a(0);
    std::cout << "in A i=" << a.get() << std::endl;
    a.set(10);
    std::cout << "in A i=" << a.get() << std::endl;
    B b(a);
    std::cout << "in B i=" << b.get() << std::endl;
    b.set(21);
    std::cout << "in B i=" << b.get() << std::endl;
    std::cout << "function returns " << function(a) << std::endl;
}

int function(A a)
{
    return a.i;
}

我能够给予B级友谊并发挥作用&#34;功能&#34;在A类中没有前瞻声明B类,或函数&#34;功能&#34;。 现在,如果我想给B类中的两个成员函数赋予友谊,那么如果我在定义A类之前没有定义B类,它就无法工作:

#include <iostream>

class B;   // doesn't work, incomplete type (complete type needed)

class A 
{
public:
    //friend class B;
    friend void B::set(int i);
    friend int B::get();
    friend int function(A a);
    A(int i);
    void set(int i);
    int get();
private:
    int i;
};

A::A(int i) : i(i)
{
}

void A::set(int i)
{
    this->i = i;
}

int A::get()
{
    return i;
}

B::B(A a) : a(a)
{
}

void B::set(int i)
{
    a.i = i;
}

int B::get()
{
    return a.i;
}

int function(A a);

int main(int argc, char *argv[])
{
    A a(0);
    std::cout << "in A i=" << a.get() << std::endl;
    a.set(10);
    std::cout << "in A i=" << a.get() << std::endl;
    B b(a);
    std::cout << "in B i=" << b.get() << std::endl;
    b.set(21);
    std::cout << "in B i=" << b.get() << std::endl;
    std::cout << "function returns " << function(a) << std::endl;
}

int function(A a)
{
    return a.i;
}

但在定义A级之前我无法定义B级,所以我被卡住了。前向声明(未定义)B类也不起作用。

所以我的问题是:

1)为什么我不需要在友谊声明中转发声明函数或整个类,但是如果我需要指定该类的成员函数,我确实需要定义一个类? 我知道友谊宣言不是一般意义上的声明(他们只是授予访问权限,他们不会向前宣布任何内容)。

2)如何编译我的代码(除了将B中的A成员对象声明为A * a)?

2 个答案:

答案 0 :(得分:1)

以下是朋友类的示例以及如何使用它。这是cplusplus.com我发布这个的原因是因为你的例子并没有真正说明在c ++中正确使用友谊。我希望这能说明你应该如何/为什么要使用友谊,这可以导致你解决你的前瞻性声明问题。

// friend class
#include <iostream>
using namespace std;

class Square;

class Rectangle {
    int width, height;
  public:
    int area ()
      {return (width * height);}
    void convert (Square a);
};

class Square {
  friend class Rectangle;
  private:
    int side;
  public:
    Square (int a) : side(a) {}
};

void Rectangle::convert (Square a) {
  width = a.side;
  height = a.side;
}

int main () {
  Rectangle rect;
  Square sqr (4);
  rect.convert(sqr);
  cout << rect.area();
  return 0;
}
  

在此示例中,类Rectangle是Square允许的类的朋友   Rectangle的成员函数用于访问私有成员和受保护成员   广场更具体地说,Rectangle访问成员变量   Square :: side,描述了正方形的一面。

     

在这个例子中还有一些新东西:在开头   程序中,有一个类Square的空声明。这是   必需因为类Rectangle使用Square(作为参数)   成员转换),而Square使用Rectangle(将其声明为朋友)。

     

除非另有说明,否则友谊永远不会对应:在我们的示例中,   Rectangle被Square视为朋友类,而Square则不是   被Rectangle视为朋友。因此,成员的职能   Rectangle可以访问Square的受保护和私有成员但是   而不是相反。当然,Square也可以宣布   如果需要,Rectangle的朋友可以授予此类访问权限。

     

友谊的另一个特性是它们不是传递性的:   除非明确表示朋友的朋友不被视为朋友   指定。

答案 1 :(得分:0)

class B成为class A的朋友。这样做没有任何不利影响。

如果你绝对肯定想要进行更细粒度的控制,你可以使用像这样的代理类(使用剥离到裸骨的例子)来实现它:

class Proxy;

class A
{
public:
    friend class Proxy;
    A(int i);
private:
    int i;
};

class B
{
public:
    B(A a);
    void set(int i);
    int get();
private:
    A a;
};

class Proxy
{
  friend void B::set(int);
  friend int B::get();
  static int& get_i(A& a) { return a.i; }
  static const int& get_i(const A& a) { return a.i; }
};

您现在可以在Proxy::get_i(a)a.i(仅限)B::set中使用B::get代替segments()