繁体   English   中英

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

[英]C++ friend classes and friend member functions

我正在学习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类授予友谊,并能够在A类中行使“功能”,而无需预先声明B类或功能“功能”。 现在,如果我想给类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)?

这是一个朋友类的示例以及如何使用它。 这是在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的成员函数访问Square的私有成员和受保护成员。 更具体地说,Rectangle访问成员变量Square :: side,该变量描述正方形的侧面。

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

除非指定,否则从不建立友谊:在我们的示例中,Square将Rectangle视为朋友类,但Rectangle不将Square视为朋友。 因此,Rectangle的成员函数可以访问Square的受保护成员和私有成员,但不能相反。 当然,如果需要,也可以将Square声明为Rectangle的朋友,以授予此类访问权限。

友谊的另一个特性是,它们不是可传递的:除非明确指定,否则朋友的朋友不会被视为朋友。

只是让class B class A class B的朋友。 这样做没有不利影响。

如果您绝对肯定要行使更细粒度的控制,则可以使用这样的代理类来做到这一点(使用剥离了示例的示例):

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; }
};

现在,您可以在B::setB::get (仅)中使用Proxy::get_i(a)代替ai

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM